node中的crypto模塊操作方法
node中的crypto模塊指南
加密操作可能很棘手,以至于付費(fèi)的加密服務(wù)公司的存在只是為了確保在代碼庫(kù)中正確實(shí)現(xiàn)加密操作。好消息是,只需學(xué)習(xí)一些知識(shí),我們就可以使用 Node 的內(nèi)置加密模塊免費(fèi)進(jìn)行適當(dāng)?shù)募用堋?/p>
在本指南中,我們將探討如何使用 Node 的內(nèi)置加密模塊正確執(zhí)行(對(duì)稱)加密/解密操作,以保護(hù)應(yīng)用程序的數(shù)據(jù)。
首先,我們需要了解對(duì)稱加密的概念。
對(duì)稱加密
當(dāng)人們談?wù)?ldquo;加密”時(shí),他們往往指的是對(duì)稱加密,這對(duì)于將文本加密為隨機(jī)字符串非常有用。與此相關(guān)的一個(gè)常見(jiàn)場(chǎng)景是對(duì)服務(wù)器上的用戶數(shù)據(jù)進(jìn)行加密,以便將其“靜態(tài)加密”存儲(chǔ)在數(shù)據(jù)庫(kù)中。
通俗地說(shuō),對(duì)稱加密就是獲取要加密的文本(稱為明文),并使用帶有加密算法的密鑰來(lái)輸出加密文本(稱為密文)。該操作是可逆的,因此解密是我們可以使用與明文相同的密鑰。

看起來(lái)很容易吧?
但是當(dāng)真正需要實(shí)現(xiàn)對(duì)稱加密時(shí),開(kāi)發(fā)人員經(jīng)常會(huì)犯錯(cuò)誤,因?yàn)橛泻芏鄸|西需要理解:
- 編碼格式:數(shù)據(jù)可以通過(guò)多種方式進(jìn)行編碼/解碼,例如
base64、hex等。當(dāng)從一種格式轉(zhuǎn)換為另一種格式時(shí),這些不同的表示方式常常使開(kāi)發(fā)人員感到困惑。算法和配置:有許多加密算法需要考慮,例如aes-256-gcm或aes-256-cbc,每種算法都有自己的要求。 - 隨機(jī)性:加密過(guò)程中使用的密鑰應(yīng)隨機(jī)生成,以確保高熵。很多時(shí)候,開(kāi)發(fā)人員認(rèn)為他們正在生成足夠隨機(jī)的密鑰,但事實(shí)并非如此。
- 復(fù)雜性:
Node.js中的加密涉及幾個(gè)步驟,這些步驟對(duì)開(kāi)發(fā)人員來(lái)說(shuō)并不總是直觀的,而且有些概念一開(kāi)始確實(shí)令人費(fèi)解。以初始化向量(IV)的概念為例;剛接觸密碼學(xué)的開(kāi)發(fā)人員經(jīng)常在加密過(guò)程中重復(fù)使用這些內(nèi)容,這是一個(gè)很大的禁忌。
無(wú)論如何,在本文中并不會(huì)討論上述細(xì)微差別,但更多地關(guān)注我們?nèi)绾瓮ㄟ^(guò)示例使用 Node.js 正確執(zhí)行加密。
解釋如何正確執(zhí)行加密的最佳方法是演示使用aes-256-gcm算法的正確實(shí)現(xiàn)。讓我們從加密開(kāi)始。
加密
const crypto = require('crypto');
const encryptSymmetric = (key, plaintext) => {
const iv = crypto.randomBytes(12).toString('base64');
const cipher = crypto.createCipheriv(
"aes-256-gcm",
Buffer.from(key, 'base64'),
Buffer.from(iv, 'base64')
);
let ciphertext = cipher.update(plaintext, 'utf8', 'base64');
ciphertext += cipher.final('base64');
const tag = cipher.getAuthTag()
return { ciphertext, tag }
}
const plaintext = "encrypt me";
const key = crypto.randomBytes(32).toString('base64');
const { ciphertext, iv, tag } = encryptSymmetric(key, plaintext);要執(zhí)行加密,我們需要兩項(xiàng):
plaintext:要加密的文本。key:256 位加密密鑰。
我們從加密中得到以下輸出:
ciphertext:加密文本。iv:一個(gè) 96 位初始化向量,用于提供加密的初始狀態(tài),并允許在未來(lái)的加密操作中以不同iv重復(fù)使用相同key。tag:在加密過(guò)程中生成的一段數(shù)據(jù),用于幫助驗(yàn)證加密文本在稍后的解密過(guò)程中沒(méi)有被篡改。
讓我們看一下代碼:
const plaintext = "encrypt me";
const key = crypto.randomBytes(32).toString('base64');這里我們定義執(zhí)行加密所需的輸入變量。除了要加密的文本之外,生成隨機(jī)數(shù)以通過(guò)更高的熵key確保安全性也很重要;我更喜歡使用內(nèi)置crypto.randomBytes()來(lái)生成。我還將所有內(nèi)容轉(zhuǎn)換為base64格式,因?yàn)樗诟拍钌弦子诖鎯?chǔ)。
接下來(lái)我們來(lái)剖析一下加密函數(shù):
const encryptSymmetric = (key, plaintext) => {
// 創(chuàng)建隨機(jī)初始化向量
const iv = crypto.randomBytes(12).toString('base64');
// 創(chuàng)建一個(gè)密碼對(duì)象
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
// 使用明文更新 cipher 對(duì)象以進(jìn)行加密
let ciphertext = cipher.update(plaintext, 'utf8', 'base64');
// 完成加密過(guò)程
ciphertext += cipher.final('base64');
// 檢索加密的身份驗(yàn)證標(biāo)簽
const tag = cipher.getAuthTag();
return { ciphertext, iv, tag };
}在這里,加密函數(shù)在使用aes-256-gcm(可以將其視為一種加密算法)算法、key和iv``crypto.createCipheriv初始化期間創(chuàng)建一個(gè)新的密碼。下一部分加載要加密的文本plaintext并執(zhí)行加密并檢索身份驗(yàn)證標(biāo)記,可以使用該標(biāo)記來(lái)檢查ciphertext解密過(guò)程中文本未被篡改。
關(guān)于加密,我們應(yīng)該了解的最后一件事是如何處理數(shù)據(jù)。在加密用戶數(shù)據(jù)并靜態(tài)存儲(chǔ)它的情況下,需要將加密的數(shù)據(jù)ciphertext、iv、 和tag存儲(chǔ)在數(shù)據(jù)庫(kù)中,并將密鑰安全地存儲(chǔ)在其他地方,例如服務(wù)器上的環(huán)境變量。當(dāng)我們想要檢索數(shù)據(jù)時(shí),可以從數(shù)據(jù)庫(kù)中查詢并使用密鑰對(duì)其進(jìn)行解密。
說(shuō)到這里,讓我們深入解密。
解密
const decryptSymmetric = (key, ciphertext, iv, tag) => {
const decipher = crypto.createDecipheriv(
"aes-256-gcm",
Buffer.from(key, 'base64'),
Buffer.from(iv, 'base64')
);
decipher.setAuthTag(Buffer.from(tag, 'base64'));
let plaintext = decipher.update(ciphertext, 'base64', 'utf8');
plaintext += decipher.final('utf8');
return plaintext;
}
const plaintext = decryptSymmetric(key, ciphertext, iv, tag);要執(zhí)行解密,我們需要四項(xiàng):
key:用于加密原始文本的256位加密密鑰。ciphertext:要解密的密文。iv:加密期間使用的 96 位初始化向量。tag:加密時(shí)生成的標(biāo)簽。
我們從加密中得到以下輸出:
plaintext:我們加密的原始文本。
讓我們看一下解密函數(shù):
const decryptSymmetric = (key, ciphertext, iv, tag) => {
// 創(chuàng)建一個(gè)解密對(duì)象
const decipher = crypto.createDecipheriv(
"aes-256-gcm",
Buffer.from(key, 'base64'),
Buffer.from(iv, 'base64')
);
// 設(shè)置解密對(duì)象 decipher 的認(rèn)證標(biāo)簽
decipher.setAuthTag(Buffer.from(tag, 'base64'));
// 使用 Base64 編碼的密文更新解密對(duì)象
let plaintext = decipher.update(ciphertext, 'base64', 'utf8');
// 完成解密
plaintext += decipher.final('utf8');
return plaintext;
}這里,解密函數(shù)在用aes-256-gcm算法進(jìn)行crypto.createDecipheriv初始化時(shí)創(chuàng)建了一個(gè)解密對(duì)象,key、iv是之前創(chuàng)建的。接下來(lái)設(shè)置身份驗(yàn)證標(biāo)簽,用于檢查是否被ciphertext篡改,最后我們執(zhí)行解密以獲得原始文本。
最后,我們的數(shù)據(jù)的安全程度取決于用于加密數(shù)據(jù)的密鑰。因此,強(qiáng)烈建議安全地存儲(chǔ)加密密鑰,并在應(yīng)用程序中將它們作為環(huán)境變量進(jìn)行訪問(wèn)。
到此這篇關(guān)于node中的crypto模塊指南的文章就介紹到這了,更多相關(guān)node crypto模塊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
nodejs實(shí)現(xiàn)bigpipe異步加載頁(yè)面方案
本文給大家分享的是使用nodejs結(jié)合bigpipe實(shí)現(xiàn)異步加載頁(yè)面的方案,非常的實(shí)用,也是以后前端性能優(yōu)化的一個(gè)方向,希望大家能夠喜歡。2016-01-01
10個(gè)Node.js庫(kù)幫助你優(yōu)化代碼和簡(jiǎn)化開(kāi)發(fā)
這篇文章主要介紹了10個(gè)Node.js庫(kù)幫助你優(yōu)化代碼和簡(jiǎn)化開(kāi)發(fā),其中包括處理數(shù)組、對(duì)象、字符串庫(kù)Lodash,緩存數(shù)據(jù)處理庫(kù)Node-cache,解析、操作和格式化日期和時(shí)間庫(kù)Moment.js,Redis操作庫(kù),發(fā)送電子郵件庫(kù)Nodemailer2023-05-05
輕松創(chuàng)建nodejs服務(wù)器(4):路由
這篇文章主要介紹了輕松創(chuàng)建nodejs服務(wù)器(4):路由,服務(wù)器需要根據(jù)不同的URL或請(qǐng)求來(lái)執(zhí)行不一樣的操作,我們可以通過(guò)路由來(lái)實(shí)現(xiàn)這個(gè)步驟,需要的朋友可以參考下2014-12-12
nodejs 實(shí)現(xiàn)模擬form表單上傳文件
使用nodejs來(lái)模擬form表單進(jìn)行文件上傳,可以同時(shí)上傳多個(gè)文件。2014-07-07
node.js使用express-jwt報(bào)錯(cuò):expressJWT?is?not?a?function解決
這篇文章主要給大家介紹了關(guān)于node.js使用express-jwt報(bào)錯(cuò):expressJWT?is?not?a?function解決的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-03-03

