基于ECDSA公私钥实现的“非对称加解密“方案(带源码)

1 篇文章 0 订阅
1 篇文章 0 订阅

需求

 

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:源码见ecc_encode.tar.gz-C++代码类资源-CSDN下载

  • 19
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值