前置知识
不了解对称加密与非对称加密的小伙伴可以看看下面的文章,想详细学习与区块链有关的加密算法可以戳这里
对称与非对称加密
https://blog.csdn.net/u013320868/article/details/54090295
ECC
ECC椭圆曲线详解(有具体实例) - Kalafinaian - 博客园 (cnblogs.com)
AES
*:https://zh.wikipedia.org/wiki/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86
ECC+AES
Bob给Alice发消息,Bob用AES密钥mB加密消息得到密文M,用Alice的公钥PA加密AES的密钥mB得到mB‘,将M和mB‘发给Alice,Alice拿到后用自己的私钥解密mB‘得到mB,再用mB解密M得到明文。
为什么不能直接用ECC进行非对称加密,要用ECC加密AES的密钥?
如果单独使用AES,没有经过加密的密钥不方便传递,很容易在传输中被截获。
如果单独使用ECC,非对称加密的速度慢、加密效率低。
因此对称与非对称加密结合可以兼顾效率和安全性,也在微信等成熟通讯软件中被广泛使用。
代码
ECC椭圆曲线加密算法目前的应用还不是很成熟,crypto-js中没有应用ECC的加密函数。
通过npm搜索eccrypto会找到一些由个人发布的package,大多涉及JavaScript中的Promise对象,不熟悉的小伙伴可以先了解一下Promise。
Promise - 廖雪峰的官方网站 (liaoxuefeng.com)
我选择了使用eccrypto-js(www.npmjs.com),这个package包含了实现AES和ECC的函数,且参数类型都是buffer,如果不能同时包含就要import不同的package,参数类型等可能不兼容,会带来一些麻烦。
该示例是前端加解密的示例,在实际应用中适用于端对端加密,不涉及服务器的加解密。
由于文章只能给出一个加密示例,没有具体的通讯接口,所以我就用注释Alice来表示Alice端,Bob来表示Bob端,并模拟Alice向Bob通讯的过程,Bob向Alice通讯就是反向过程,不多赘述。加解密得到的信息输出到控制台中。
PS:
1.在代码中,ECC的公私钥和AES的密钥都是随机产生的,实际生产中私钥通常和钱包或者账户关联。
2.加解密和通讯过程中都是使用buffer类型,在控制台显示时注意转换成string。
import * as eccryptoJS from ‘eccrypto-js‘ //加解密函数的参数都是buffer类 //Alice //一个新的随机的32字节私钥,私钥对应的未压缩(65字节)公钥。 const keyPairA = eccryptoJS.generateKeyPair(); console.info("privateKey:", keyPairA.privateKey); console.info("publicKey:", keyPairA.publicKey); //send publicKey to Bob //Bob //随机生成AES的密钥 const AESKey = eccryptoJS.randomBytes(32); console.info("AESKey:", AESKey); const iv = eccryptoJS.randomBytes(16); //用ECC加密AES密钥 const EncryptedAESKey = await eccryptoJS.encrypt(keyPairA.publicKey, AESKey); console.info("EncryptedAESKey:", EncryptedAESKey); //待发送的明文str,先转成buffer格式 const str = ‘test message to encrypt‘; const msg = eccryptoJS.utf8ToBuffer(str); //用未加密的AES密钥加密明文 const ciphertext = await eccryptoJS.aesCbcEncrypt(iv, AESKey, msg); console.info("ciphertext:", ciphertext); //send 密文encrypt_str and AESKeyEncrypt to Alice,iv? //Alice //用私钥解密加密后的AES密钥 const DecryptedAESKey = await eccryptoJS.decrypt(keyPairA.privateKey, EncryptedAESKey); console.info("decryptedAESKey:", DecryptedAESKey); //用AES密钥解密明文 const decrypted = await eccryptoJS.aesCbcDecrypt(iv, DecryptedAESKey, ciphertext); console.info("decrypted:", decrypted.toString());
ECC(Ellipse Curve Cryptography)+AES(Advanced Encryption Standard)前端通讯加密模拟(使用eccrypto-js)