文章是我整理出來的筆記略微粗糙,記錄crypto庫的簡單了解和用法。
-
crypto
-
Hash(散列)算法
-
Hmac算法
-
PBKDF2函數
-
對稱加密
-
小結
文中主要介紹node 的cypto模塊,結合前端
crypto-js演示(crypto-js是javascript 實現的cypto庫)。
1. crypto
Crypto++ 庫是一個用c++ 編寫的密碼類庫,提供完整的加密實現,並且通常包括不太流行,不常使用的方案。(簡單說:crypto 是一個包括了加解密算法的庫)
node crypto 模塊提供了加密功能,包括對 OpenSSL 的哈希、HMAC、加密、解密、簽名、以及驗證功能的一整套封裝。
2.Hash(散列)算法
哈希算法將任意長度的輸入通過散列算法變換成固定長度的輸出,該輸出就是hash值,常見的有md5,sha1,sha256等。

舉個例子:服務端將文件計算出哈希值,當客戶端下載文件也計算出哈希值,然后比對,文件是否下載完畢。假設此時的文件信息是hello world,當雙方的文件信息一致時,算出的hash值也一致。
node:
const crypto = require('crypto') //創建並返回一個 Hash 對象,該對象可用於生成哈希摘要(參數為給定的算法)。 // const hash = crypto.createHash('md5'); const hash = crypto.createHash('sha256') // 可任意多次調用update(): // 指定要摘要的原始內容,可以在摘要被輸出之前使用多次update方法來添加摘要內容 hash.update('Hello, world!') hash.update('Hello, nodejs!') // 計算傳入要被哈希(使用 hash.update() 方法)的所有數據的摘要。 // 如果提供了 encoding,則返回字符串,否則返回 Buffer。 console.log(hash.digest('hex').length)
crypto-js:
let crypto = require('crypto-js') let hash = crypto.algo.SHA256.create() hash.update('Hello, world!') hash.update('Hello, nodejs!') let result = hash.finalize() // WordArray object console.log(result.toString(crypto.enc.Hex));
node的Hash類:
crypto.createHash() 方法用於創建 Hash 實例
Hash 類是一個實用工具,用於創建數據的哈希摘要。 它可以通過以下兩種方式之一使用:
-
作為可讀寫的流,其中寫入數據以在可讀側生成計算后的哈希摘要(繼承自: </stream.Transform>)。
-
使用 hash.update() 和 hash.digest() 方法生成計算后的哈希。
3. Hmac算法
HMAC算法將散列(hash)算法與一個密鑰結合在一起,以阻止對簽名完整性的破壞,密鑰發生了變化,輸出結果也會發生變化.(Hmac可以理解為用隨機數“增強”的哈希算法)
還是上面的例子換個算法
node:
let crypto = require('crypto') // 密鑰 let key = '密鑰' // 選定的摘要算法 sha256 選的密鑰 key let hmac = crypto.createHmac('sha256',key) hmac.update('Hello, world!'); hmac.update('Hello, nodejs!'); let result = hmac.digest('hex'); console.log(result)
crypto-js:
let CryptoJS = require('crypto-js') // 密鑰 let key = '密鑰' // 密鑰 keyBit 摘要算法 sha256 let hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); hmac.update('Hello, world!') hmac.update('Hello, nodejs!') let result = hmac.finalize() // WordArray object console.log(result.toString(CryptoJS.enc.Hex));
node crypto Hmac 類:
crypto.createHmac() 方法用於創建 Hmac 實例
Hmac 類是一個實用工具,用於創建加密的 HMAC 摘要。 它可以通過以下兩種方式之一使用:
-
作為可讀寫的流,其中寫入數據以在可讀側生成計算后的 HMAC 摘要(繼承自: </stream.Transform>)。
-
使用 hmac.update() 和 hmac.digest() 方法生成計算后的 HMAC 摘要。
4.PBKDF2函數
PBKDF2:是一個用來導出密鑰的函數,常用於生成加密的密碼
基本原理:通過一個偽隨機函數(例如HMAC函數),把明文和一個鹽值作為輸入參數,然后重復進行運算,並最終產生密鑰。
node:
let crypto = require('crypto') let password = 'luoxiaobuhaha' // 用來生成密鑰的原文密碼 let salt = 'salt' // 一個加密用的鹽值。 let iterations = 10000 // 迭代次數 let keylen = 16 // 期望得到秘鑰的長度 // 由選擇HMAC摘要算法,digest 以導出所請求的字節長度 let digest = 'sha256' // 一個偽隨機函數 crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, derivedKey) => { if (err) throw err console.log(derivedKey.toString('hex')) })
crypto-js:
let CryptoJS = require('crypto-js') var derivedKey = CryptoJS.PBKDF2(password, salt, { keySize: 4, // // WordArray object iterations: iterations, hasher: CryptoJS.algo.SHA256 }); console.log(derivedKey.toString(CryptoJS.enc.Hex))
crypto.pbkdf2提供異步的基於密碼的密鑰派生功能2(PBKDF2)實現。由指定的選擇HMAC摘要算法digest被施加以導出所請求的字節長度。也有同步方法,更多細節參考文檔。
5.對稱加密
對稱加密算法,加解密都用同一個密鑰。

node:
let crypto = require('crypto') // data:需要加解密的內容, // key: 密鑰 // 初始化向量(iv) function aesEncrypt(data, key, iv) { // 給定的算法,密鑰和初始化向量(iv)創建並返回Cipher對象 const cipher = crypto.createCipheriv('aes-192-cbc', key, iv) // Key length is dependent on the algorithm. In this case for aes192, it is 24 bytes (192 bits). // 指定要摘要的原始內容,可以在摘要被輸出之前使用多次update方法來添加摘要內容 // 數據的編碼 utf8 返回值的編碼 hex var crypted = cipher.update(data, 'utf8', 'hex') crypted += cipher.final('hex') return crypted } function aesDecrypt(data, key, iv) { // 給定的算法,密鑰和初始化向量(iv)創建並返回Cipher對象 const decipher = crypto.createDecipheriv('aes-192-cbc', key, iv) // 數據的編碼 hex 返回值的編碼 utf8 var decrypted = decipher.update(data, 'hex', 'utf8') decrypted += decipher.final('utf8') return decrypted } const IV = 'f710b45f04e37709' // 初始化向量(iv) let data = 'luoxiaobu' // 需要加解密的內容, let key = '123456789987654321123456' // 24 位秘鑰密鑰 let encryptData = aesEncrypt(data, key, IV) let decryptData = aesDecrypt(encryptData, key, IV) console.log(encryptData) console.log(decryptData)
輸出:
b98a1d87ea00fb47ade2d9cff0a9179d
luoxiaobu
crypto-js:
const CryptoJS = require('crypto-js') const IV = CryptoJS.enc.Utf8.parse('f710b45f04e37709') // 十六位十六進制數作為密鑰偏移量 let data = 'luoxiaobu' // 需要加解密的內容, let key = CryptoJS.enc.Utf8.parse('123456789987654321123456') // 24 位秘鑰密鑰 function decrypt(data, key, iv) { let dataHexStr = CryptoJS.enc.Hex.parse(data); let dataBase64 = CryptoJS.enc.Base64.stringify(dataHexStr); // 接收的數據是 base64 let decrypt = CryptoJS.AES.decrypt(dataBase64, key, { iv: iv, mode: CryptoJS.mode.CBC}); let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8); return decryptedStr.toString(); } //加密方法 function encrypt(data, key, iv) { let encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv, mode: CryptoJS.mode.CBC}); return encrypted.ciphertext.toString().toUpperCase();; } let encryptData = encrypt(data, key, IV) let decryptData = decrypt(encryptData, key, IV) console.log(encryptData) console.log(decryptData)
輸出:
b98a1d87ea00fb47ade2d9cff0a9179d
luoxiaobu
補充:
AES是一種常用的對稱加密算法。加密的分組模式有ECB/CBC/CFB/OFB
分組密碼又稱為秘密鑰密碼或對稱密碼。利用分組密碼對明文進行加密時,首先需要對明文進行分組,每組的長度都相同,然后對每組明文分別加密得到等長的密文,分組密碼的特點是加密密鑰與解密密鑰相同。 分組密碼的安全性應該主要依賴於密鑰,而不依賴於對加密算法和解密算法的保密。因此,分組密碼的加密和解密算法可以公開。
node cropty Cipher 類 ,node cropty Decipher類 具體使用參考文檔
6.小結
文章是我整理出來的筆記略微粗糙,記錄crypto庫的簡單了解和用法,理解不准確之處,歡迎一起討論學習。
關於crypto庫還常用的有非對稱加密算法,以及簽名,之后也會修正補上。
資料: