文章是我整理出来的笔记略微粗糙,记录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库还常用的有非对称加密算法,以及签名,之后也会修正补上。
资料: