基础准备工作
const secret = 'Sunshine'
const salt = 'Treasure'
const plainText = '始终相信美好的事情即将发生'
const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7ikxFcifEdVZ7IxSvd65vUQKx
xvYZRx+qSz0Cl1Xj+PwyT9hnw4M6rglvbjgpQhQnnumY/KkmI7CCglXVNjOI9zRA
/IfSv3juPTEFItJUcnfOtgnzDgrzMvu9gP9nH45aD5mnZd+zWaK9BSJSuOk/D6rj
Lts8Iykv1jpQ/KYFPwIDAQAB
-----END PUBLIC KEY-----`
const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQC7ikxFcifEdVZ7IxSvd65vUQKxxvYZRx+qSz0Cl1Xj+PwyT9hn
w4M6rglvbjgpQhQnnumY/KkmI7CCglXVNjOI9zRA/IfSv3juPTEFItJUcnfOtgnz
DgrzMvu9gP9nH45aD5mnZd+zWaK9BSJSuOk/D6rjLts8Iykv1jpQ/KYFPwIDAQAB
AoGAQdV0nNRL/X0rVKKl+krLIyyPA5VSguEizocG7cfuUM7wyUCaOSK7CHhbu5A3
itQ1ewsf+aKIRmk05zuVofka8ZkOxfdpMgNlP1nuYD6VQHbm6ssPiZP64EX1W64G
djNnOhZjP1dR/JhEMB8tWZDdQOhwHMiTCWGMZZYXtC7aUdECQQDz05OZM2eTZkeu
5srHLVDLWrNTn6yZCnD4PA7ltyuR2uF3K/dziWaCPT6J8dblOnBKJteU0fvMiDPx
iT8KyM7LAkEAxOdPHQ6+k9s/25tpmEXibJytJ8T1HsIxFAdvuHqurjMnb3yOg2F+
0s2fBnH42nvYnJmCA2TDv39G9EczHvKA3QJAAnaCqSuBwlVoJ/Yg2j408Ljr0s5s
GeenGHrS07Mz93c0i9Wf3ETpCivAM/iDaTFb7QPTbadpWbmOfMQcJOm+XQJAMKzh
wNQpRpHXqmkz5GG6RJFCuOcWlWD6EvJ3qsohLo0UvZmz/UR3vpL4MfawxwoAlU3Z
dw9M2KUVHEQRnh/ivQJAD+U1zCsmP6J3+gWZ/lzGE+8CrfxhjywSTtEAsC1GhAA8
BnaJUPhgGM9r9N52NWb/WuhT1PgLZSlW0OhBX1/xJg==
-----END RSA PRIVATE KEY-----`
对称密码
一种用相同的密钥进行加密和解密的技术,用于确保消息的机密性。在对称密码的算法方面,目前主要使用的是 AES。经管对称密码能够确保消息的机密性,但需要解决将解密密钥配送给接收者的密钥配送问题
test('对称密码', () => {
//TODO 没有通过测试,报错 error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
const cipher = crypto.createCipher('aes192', secret)
cipher.update(Buffer.from(plainText))
const cipherText = cipher.final()
const deCipher = crypto.createDecipher('aes192', secret)
deCipher.update(cipherText)
const temp = deCipher.final()
expect(temp).toBe(Buffer.from(plainText))
})
公钥密码
一种用不同的密钥进行加密和解密的技术,和对称密码一样用于确保消息的机密性。使用最广泛的算法是 RSA,除此之外还有 ElGamal 和 Robin 等算法,以及与其相关的Diffie-Hellman 密钥交换和椭圆曲线 Diffie-Hellman 密钥交换等技术。和对称密码相比,公钥密码的速度非常之慢,因此一般都会和对称密码一起组成混合密码系统来使用。公钥密码能够解决对称密码中的密钥交换问题,但存在通过中间人攻击被伪装的风险,因此需要对带有数字签名的公钥进行认证
test('公钥密码', () => {
const publicText = crypto.publicEncrypt(publicKey, Buffer.from(plainText))
const privateText = crypto.privateDecrypt(privateKey, publicText)
expect(privateText.toString()).toBe(plainText)
})
单向散列函数
一种将长消息转换为短散列值的技术,用于确保信息的完整性。在单向散列函数的算法方面,SHA-1 曾被广泛使用,但由于人们已经发现了一些针对该算法的理论上可行的攻击方式,因此该算法不再被用于新的用途。今后我们应该主要使用的算法包括目前已经在广泛使用的 SHA-2,以及具有全新结构的SHA-3算法。单向散列函数可以单独使用,也可以用作消息认证码、数字签名以及伪随机数生成器等技术的组成元素来使用
test('单向散列函数', async () => {
const hash = crypto.createHash('sha256')
// 一般对公钥进行散列
hash.update(publicKey)
const hex = hash.digest('hex')
expect(hex).not.toBeNull()
})
消息认证码
一种能够识别通信对象发送的消息是否被篡改的认证技术,用于验证消息的完整性,以及对消息进行认证。消息认证码的算法中,最常用的是利用单向散列函数的 HMAC。HMAC 的构成不依赖于某一种具体的单向散列函数算法。消息认证码能够对通信对象进行认证,但无法对第三方进行认证。此外,它也无法防止否认。消息认证码也可以用来实现认证加密。
test('消息认证码', () => {
const hmac = crypto.createHmac('sha256', salt)
hmac.update(plainText)
const msg = hmac.digest('hex')
expect(msg).not.toBeNull()
})
数字签名
是一种能够对第三方进行信息认证,并能够防止通信对象做出否认的认证技术。数字签名的算法包括RSA、ElGamal、DSA、椭圆曲线DSA、爱德华兹曲线DSA等。公钥基础设施 PKI 中使用的证书,就是对公钥加上认证机构的数字签名所构成的。要验证公钥的数字签名,需要通过某种途径获取认证机构的自身的合法公钥。
test('数字签名', () => {
const sign = crypto.createSign('RSA-SHA256')
const signature = sign.sign(privateKey)
const verify = crypto.createVerify('RSA-SHA256')
expect(verify.verify(publicKey, signature)).toBeTruthy()
})
伪随机数生成器
一种能够生成具备不可预测性的比特序列的技术,由密码和单向散列函数等技术构成。伪随机数生成器用于生成密钥、初始化向量和 nonce 等
test('伪随机数生成器', () => {
const random = crypto.randomBytes(256).toString('hex')
console.log(random)
expect(random.length).toBe(512)
})
完整代码
github
欢迎star
网友评论