非对称加密与对称加密相比,安全性要高很多。对于对称加密,密钥钥匙被某一方不小心泄露了,那秘文就有可能被破解和篡改。而非对称加密,公钥随意流通,只要颁发密钥的一方好好把私钥保管好,安全性是妥妥的。
编码实现
我们来看 node 中的编码实现,还是使用官方提供的 crypto 库
const constants = require('constants') const crypto = require('crypto') /** * @description * 公钥加密数据 * @param {*} data 待加密数据 * @param {*} publicKey 公钥 * @param {*} inputEncoding 加密数据类型 * @param {*} outputEncoding 输出的数据类型 * @param {*} padding 填充方式 * @returns */ function publicEncrypt(data, publicKey, inputEncoding, outputEncoding, padding) { const encryptText = crypto.publicEncrypt({ key: publicKey, padding: padding || constants.RSA_PKCS1_PADDING }, Buffer.from(data, inputEncoding)); return encryptText.toString(outputEncoding); } /** * @description * 公钥解密数据 * @param {*} data 待解密数据 * @param {*} publicKey 公钥 * @param {*} inputEncoding 解密数据类型 * @param {*} outputEncoding 输出的数据类型 * @param {*} padding 填充方式 * @returns */ function publicDecrypt(data, publicKey, inputEncoding, outputEncoding, padding) { let decryptText = ''; const decryptText = crypto.publicDecrypt({ key: publicKey, padding: padding || constants.RSA_PKCS1_PADDING }, Buffer.from(data, inputEncoding)); return decryptText.toString(outputEncoding); } /** * @description * 私钥加密数据 * @param {*} data 待加密数据 * @param {*} privateKey 私钥 * @param {*} inputEncoding 加密数据类型 * @param {*} outputEncoding 输出的数据类型 * @param {*} padding 填充方式 * @returns */ function privateEncrypt(data, privateKey, inputEncoding, outputEncoding, padding) { const encryptText = crypto.privateEncrypt({ key: privateKey, padding: padding || constants.RSA_PKCS1_PADDING }, Buffer.from(data, inputEncoding)); return encryptText.toString(outputEncoding); } /** * @description * 私钥解密数据 * @param {*} data 待解密数据 * @param {*} privateKey 私钥 * @param {*} inputEncoding 解密数据类型 * @param {*} outputEncoding 输出的数据类型 * @param {*} padding 填充方式 * @returns */ function privateDecrypt(data, privateKey, inputEncoding, outputEncoding, padding) { const decryptText = crypto.privateDecrypt({ key: privateKey, padding: padding || constants.RSA_PKCS1_PADDING }, Buffer.from(data, inputEncoding)); return decryptText.toString(outputEncoding); }
有四个函数,分别是公钥的加解密和私钥的加解密,我们看下如何使用,示例中是我自己生成的密钥对,大家可以自行替换
const rsaPublicKey = `-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCncWDMXEToSxtGQCmWY2ywl5CQ tb81PXYZch4v5M8MNUZPpcmf+VDXQbuWqqTqV/tY7rLviu/BAkFbX9NiFCapF5lP siVwSGWJQwq0S/++RCwB6yFVEzOKL25jANRBVNwmSOzojveCStYPcEs5Q829ld68 9TzluDDqUS69dTHGkQIDAQAB -----END PUBLIC KEY-----` const rsaPrivateKey = `-----BEGIN PRIVATE KEY----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKdxYMxcROhLG0ZA KZZjbLCXkJC1vzU9dhlyHi/kzww1Rk+lyZ/5UNdBu5aqpOpX+1jusu+K78ECQVtf 02IUJqkXmU+yJXBIZYlDCrRL/75ELAHrIVUTM4ovbmMA1EFU3CZI7OiO94JK1g9w SzlDzb2V3rz1POW4MOpRLr11McaRAgMBAAECgYEAhNa8/cQh4sxbKgOTOr1MKFlG Fpgpxroo7I0Nh9+Vp1DIpD2Z1PF9ghijEyf0R/pe7LIKgWIPTWdVpIFEeSYVeH43 FLr3zwR9oXzwG7RQTSN4d/Xcvg+24ZxCrvDfn7qDIlXh0jOS0wCvna1or7xgPcOu XG8J3BNbBdUixM0lk0ECQQDR4SCelWn0BY21jsFobX+pGqKOsj+tuvU4Cz47Gmev qvq2suYXwLemkP7EqRu8iNso/IzvrdsuJDG76dzwC4D5AkEAzDz2cDrKOVmqYw7s luOQFHl1TzmY7Umpd9YbZ5iXn0eCjIn1/e1risRF5+IeSpB84OVltUzj4cVDCbFd 9S1wWQJAIeKcFp5+9cPzxi1fMpIDO3Uua6WBvHXj44GFMZuow+byBY9KsOkPfZgJ Wg0Hil/6KlrkEkpaic+ULAetASCKWQJAdMh/Gdlj/LsaxJ2qBvWEU1DIFU8X9Mbk ElPpQ6lrOXaIXZgdgt8ZWTW1y0vuijBoV6iUKcEXpOdI1+gFk8YxsQJBAJsGJClf E1mE6CZgegM82428g4osZznVXBO/QtrQsA78S1xo8bo4qwVm0jQBcto65gwlfeeB Xm7MiIvNVBqzTVs= -----END PRIVATE KEY----- ` const str = 'xiaoliye' const cipherText = publicEncrypt(str, rsaPublicKey, 'utf8', 'hex') // 公钥加密 const decryptText = privateDecrypt(cipherText, rsaPrivateKey, 'hex', 'utf8') // 私钥解密 console.log(str === decryptText) // true const cipherTextPrivate = privateEncrypt(str,rsaPrivateKey,'utf8', 'hex') // 私钥加密 const decryptTextPublic = publicDecrypt(cipherTextPrivate,rsaPublicKey, 'hex', 'utf8') // 公钥解密 console.log(str === decryptTextPublic) // true
密钥生成方式
网上有很多工具可以一键生成配对的公钥和私钥,淘宝、微信都有提供相关工具,或者使用 OpenSSL 生成也可以。
摘要算法(HASH)
把任意长度的输入,根据算法生成一串固定长度的伪随机数,这一算法就是摘要算法,它有这么几个特点
不需要密钥,加密出来的数据无法被解密,具有不可逆性。
生成的摘要长度是固定的,与输入无关。
相同的输入,使用相同的实现,生成的摘要一定相同;不同的输入,生成的摘要是大相径庭的,即,不会发生碰撞。
根据这些特点,摘要算法通常用于生成签名,用来验证数据的完整性。