简介加密
加密是
以某种算法改变原有的信息数据,使得未授权用户即使获得了已加密信息,因不知解密的方法,无法得知信息真正的含义通过这种方式提高网络数据传输的安全性.
加密算法常见的有一下五类:
哈希算法HMAC 算法签名、对称性加密算法非对称性加密算法
加密算法也分为
可逆和不可逆,比如 md5 就是不可逆加密,只能暴力破解(撞库),node利用 OpenSSL库来实现它的加密技术,crypto 模块提供了加密功能,包含对OpenSSL的哈希、HMAC、加密、解密、签名以及验证功能的一整套封装,核心模块,使用时不需安装。
第一类 - hash算法/哈希算法/散列算法
- 用来把任意长度的输入变换成固定长度的输出
- 常见的有 md5、sha1,还有例如sha256,sha512,ripemd160-
crypto.getHashes()方法用于查看支持的加密算法
md5 - 也叫’摘要算法’
- 具有以下几个特点
- 不可逆;
- 不管加密的内容多长,最后输出的结果长度都是相等的;
- 内容不同输出的结果完全不同,内容相同输出的结果完全相同
暴力破解
由于相同的输入经过 md5 加密后返回的结果完全相同,所以破解时通过 “撞库” 进行
暴力破解,当连续被 md5 加密 3 次以上时就很难被破解了,所以使用 md5 一般会进行多次加密使用
1
2
3
4let md5 = crytpo.createHash("md5"); // 创建 md5
let md5Sum = md5.update("123"); // update 加密
let result = md5Sum.digest(); // 获取加密后结果
// result <Buffer 20 2c b9 62 ac 59 07 5b 96 4b 07 15 2d 23 4b 70>
update方法的返回值就是 this,即当前实例,所以支持链式调用,
较长的信息也可以多次调用 update 方法进行分段加密,调用 digest 方法同样会返回整个加密后的值
1 | crypto |
digest 方法参数用于指定加密后的返回值的格式,
不传参默认返回加密后的 Buffer,常用的参数有 hex 和 Base64,hex 代表十六进制,加密后长度为 32,Base64 的结果长度为 24,以 == 结尾
1 | crypto.createHash('md5').update('123').digest('hex') // 202cb962ac59075b964b07152d234b70 |
第二类 Hmac 算法 - 也叫加盐算法
是将
哈希算法与一个密钥结合在一起,用来阻止对签名完整性的破坏,同样具备 md5 加密的几个特点。使用
1
crypto.createHmac("sha1", "salt").update('admin123').digest('hex'); // 629a619b75bd12ecb66a749558ba5b4f9703d531
createHmac(‘加密的算法’,’密钥’) - 第一个参数同 crytpo.createHash,为
加密的算法,常用 sha1 和 sha256,第二个参数为密钥
digest 方法生成的加密结果长度要大于 md5(
因为Hmac算法常用 sha1 和 sha256),hex 生成的结果长度为 64,Base64 生成的结果长度为 44,以 = 结尾
创建密钥的方法
- 可以安装 openSSH 客户端,并通过命令行生成存储密钥的文件,命令如下。
openssl genrsa -out rsa_private.key 1024
openssl genrsa 代表生成密钥,-out 代表输出文件,rsa_private.key 代表文件名,1024 代表输出密钥的大小
1 | // 直接读取密钥文件配合加盐算法加密 |
第三类 对称性加密
对称性加密是
发送数据时使用密钥和加密算法进行加密,接收数据时需要使用相同的密钥和加密算法的逆算法(解密算法)进行解密,也就是说对称性加密的过程是可逆的,crypto 中使用的算法为blowfish使用
1 | // 对称性加密 |
- 加密使用 crypto.createCipher 方法,解密使用 crypto.createDecipher 方法,但是使用的算法和密钥必须相同,需要注意的是解密过程中 update 中需要在第二个参数中指定加密时的格式,如 hex,在 final 还原数据时需要指定加密字符的编码格式,如 utf8。
第四类 非对称性加密
非对称性加密相也是
可逆的,较于对称性加密要更安全,消息传输方和接收方都会在本地创建一对密钥,公钥和私钥,互相将自己的公钥发送给对方,每次消息传递时使用对方的公钥加密,对方接收消息后使用他的私钥解密,这样在公钥传递的过程中被截获也无法解密,因为公钥加密的消息只有配对的私钥可以解密。使用 openSSH 对之前生成的私钥 rsa_private.key 产生一个对应的公钥
openssl rsa -in rsa_private.key -pubout -out rsa_public.key
上面的命令意思根据一个私钥生成对应的公钥,-pubout -out 代表公钥输出,rsa_public.key 为公钥的文件名
1 | // 非对称性加密 |
使用公钥加密的方法是 crypto.publicEncrypt,第一个参数为公钥,第二个参数为
加密信息(必须是 Buffer),使用私钥解密的方法是 crypto.privateDecrypt,第一个参数为私钥,第二个参数为解密的信息。
签名
签名与非对称性加密非常类似,同样有公钥和私钥,不同的是使用私钥加密,对方使用公钥进行解密验证,以确保这段数据是私钥的拥有者所发出的原始数据,且在网络中的传输过程中未被修改。
- 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 签名
const fs = require("fs");
const crypto = require("crypto");
const path = require("path");
// 获取公钥和私钥
let publicKey = fs.readFileSync(path.join(__dirname, "rsa_public.key"), "ascii");
let privateKey = fs.readFileSync(path.join(__dirname, "rsa_private.key"), "ascii");
// 生成签名
let sign = crypto.createSign("RSA-SHA256");
sign.update("admin123");
let signed = sign.sign(privateKey, "hex");
// 验证签名
let verify = crypto.createVerify("RSA-SHA256");
verify.update("admin123");
let verifyResult = verify.verify(publicKey, signed, "hex");
console.log(verifyResult); // true
生成签名的 sign 方法有两个参数,第一个参数为
私钥,第二个参数为生成签名的格式,最后返回的 signed 为生成的签名(字符串)。
验证签名的 verify 方法有三个参数,第一个参数为公钥,第二个参数为被验证的签名,第三个参数为生成签名时的格式,返回为布尔值,即是否通过验证。
总结
createHash - 哈希算法,常用md5的方式,还有sha1,sha256等,不可逆,加密源数据一样生成的结果一样,长度固定。
createHmac - 用随机数“增强”的哈希算法,加salt,常用sha1,sha256等方式加密。
对称性加密 - 使用相同的密钥进行加密和解密处理
非对称性加密 - 双方都生成一对公钥和私钥,APublic,APrivate,BPublic,BPrivate,将自己的公钥都给对方,然后传输前使用对方的公钥加密,使用自己的私钥进行解密
签名 - 使用私钥进行加密,然后传输,最后通过公钥进行解密