ECC(Ellipse Curve Cryptography)+AES(Advanced Encryption Standard)前端通訊加密模擬(使用eccrypto-js)

榴蓮千層ya發表於2021-08-21

 前置知識

不瞭解對稱加密與非對稱加密的小夥伴可以看看下面的文章,想詳細學習與區塊鏈有關的加密演算法可以戳這裡

對稱與非對稱加密

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());

 

相關文章