基於ECDSA公私鑰實現的"非對稱加解密"方案(帶源碼)

需求

ECDSA(elliptic curve digital signature algorithm) 橢圓曲線數字簽名算法是區塊鏈應用常用的簽名算法(例如比特幣,騰訊的trustsql等),這個算法具有速度快,強度高,簽名短等特點。這個算法適合用於簽名,但是在openssl庫裏找不到對應的加解密方案。

在工作中遇到這樣的需求,區塊鏈用戶(客戶端)本身已經擁有了ECDSA的公私鑰,現在服務端想基於客戶端的ECDSA公私鑰實現加密內容傳輸(非對稱加密)。

通過研究,發現可以通過以下組合的方式來實現基於ECDSA公私鑰的非對稱加解密。

封裝

首先總共封裝了三個函數:生成公私鑰,公鑰加密私鑰解密,一目瞭然。

//生成ECDSA公私鑰(16進制編碼)
int ECDSA_GenKeyBase16(std::string &sPrikeyB16, std::string &sPubkeyB16);
//使用公鑰加密
int ECDSA_Encode(const std::string &sPlaintext, const std::string &sPubkeyB16, std::string &sCiphertext);
//使用私鑰加密
int ECDSA_Decode(const std::string &sCiphertext, const std::string &sPrikeyB16, std::string &sPlaintext);
 

 流程和原理

第一步:客戶端生成公私鑰

首先客戶端本地調用ECHDS_GenKeyBase16函數生成16進制編碼的ECDSA私鑰CliPriKeyB16和ECDSA公鑰CliPubKeyB16,然後將公鑰CliPubKeyB16上傳到服務端。

int ECDSA_GenKeyBase16(std::string &sPrikeyB16, std::string &sPubkeyB16);

第二步:服務端加密

服務端調用加密函數ECDSA_Encode,輸入明文Splaintext和客戶端上傳的公鑰CliPubKeyB16,輸出密文sCiphertext。

int ECDSA_Encode(const std::string &sPlaintext, const std::string &sPubkeyB16,std::string &sCiphertext);

輸出的密文sCiphertext結構如下圖所示:

 

報文分成四個部分:
第一部分(secure_head_t):存儲的是一個結構體的二進制信息,長度是32字節,結構體如下描述

typedef struct 
{
    uint64_t key_len;     //祕鑰協商的隨機key
    uint64_t hmac_len;    //hmac長度
    uint64_t orig_len;    //原始明文長度
    uint64_t body_len;    //密文長度
} secure_head_t;

 實際上結構體裏面存儲了第二,三,四部分的報文長度(字節)。同時還保存了原始明文(sPlaintext)的長度。

第二部分(key):服務端隨機生成ECDSA私鑰SerPriKeyB16和對應公鑰SerPubKeyB16,把SerPubKeyB16做編碼轉換存儲爲key。

第三部分(body):對明文信息sPlaintext進行AES對稱加密後得到body,body的生成過程如下
1,使用ECDH祕鑰協商,輸入參數:a)客戶端的公鑰CliPubKeyB16;b)服務端私鑰SerPriKeyB16。輸出參數:協商出一個結果envelope_key(64字節)。

2,用envelope_key的前32個字節作爲AES對稱祕鑰, 對sPlaintext加密得到body。

第四部分(hmac):校驗信息,生成過程如下:

1,使用envelope_key的後32個字節作爲HMAC算法的祕鑰,對body計算得出hmac值(後續作校驗用)。

第三步:客戶端解密

客戶端從服務商得到sCiphertext後,根據私鑰CliPriKeyB16調用ECDSA_decode函數進行解密

int ECDSA_Decode(const std::string &sCiphertext, const std::string &sPrikeyB16,std::string &sPlaintext);

解密過程如下:

1,通過第一部分的secure_head_t計算長度,分別得到二,三,四部分的key,body和hmac。

2,使用ECDH祕鑰協商,輸入參數:a)客戶端私鑰CliPriKeyB16;b)服務端公鑰(通過透傳過來的key換算得來)。輸出參數:協商出一個結果envelope_key(64字節),envelope_key等價於第二步生成的envelope_key。

3,使用envelope_key的後32個字節作爲HMAC算法的祕鑰,對body計算得出hmac`值,比較hmac`是否等於hmac,如果不等於說明數據已經被損壞,如果等於則跳到第4步。

4,用envelope_key的前32個字節作爲AES對稱祕鑰,對body解密得到明文sPlaintext。

ps:源碼見附件

發佈了6 篇原創文章 · 獲贊 5 · 訪問量 2454
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章