一、介绍:
因为最近设计一些密钥交换相关的协议,做了很多调研,和学习。本来想直接使用ECC完成密钥交换协议,但是现存的很多代码都是基于ECDH的,这完全不是基于ECC加密的。尝试了很久之后终于自己手写了一份加密方案出来,为了方便更好的加解密,我封装成数组进行了,可自行更改。属实不易,全网独一份,希望大家点个赞,拷贝请声明。
二、代码:
请容我简单介绍一下思路:
其实在ECC相关开源库里可以看出并没有直接的加密解密。所以的咱们如何实现加密呢——点乘,m = a*G*c,a是私钥,c是明文,m是密文,a为私钥,G为基点,如果已知m、G,就无法破解获得c。如果解密只需要m乘a的逆。再说一些细节:
1:c是字符串,想要实现乘必须先将c转换成一种大数,再用大数点乘;
2:a的逆如何求,我们要先获得椭圆曲线的阶n,a*x % n =1,x为a的逆。所以先获得阶n,再用大数库求逆。
3:为了更方便的输出,我将所有大数转成16进制输出,在很多场景中不需要解密,我们可以采用div参数设置输出16进制字符串的长度。
4:点赞、收藏,不然以后这么良心的作品要收费了!
ECDH.cpp
void myECC::encrypt(std::string key, std::vector<std::string> &plaintext, std::vector<std::string> &strCipher_list, unsigned long long size, int div){
BIGNUM *key_big = BN_new();
char *hex_pk;
BN_dec2bn(&key_big, (char *)key.data());//随机数转换成大数
//建立椭圆曲线
EC_KEY *ecdh = EC_KEY_new();
EC_GROUP *group;
EC_POINT *point_mul_aG, *point_mul_aGp;
const EC_POINT *generator;
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);//NID_secp521r1
group = (struct ec_group_st *) EC_KEY_get0_group(ecdh);
point_mul_aG = EC_POINT_new(group);
point_mul_aGp = EC_POINT_new(group);
//获得基向量
generator = EC_GROUP_get0_generator(group);
//获得a*G
EC_POINT_mul(group, point_mul_aG, NULL, generator, key_big, NULL);
if(div) {
for (int i = 0; i < size; ++i) {
BN_dec2bn(&key_big, (char *) plaintext[i].data());
EC_POINT_mul(group, point_mul_aGp, NULL, point_mul_aG, key_big, NULL);
//hex_pk = EC_POINT_point2hex(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, NULL);
EC_POINT_point2bn(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, key_big, NULL);
hex_pk = BN_bn2dec(key_big);
strCipher_list.push_back(((std::string) hex_pk).substr(0, div));
}
}else{
for (int i = 0; i < size; ++i) {
BN_dec2bn(&key_big, (char *) plaintext[i].data());
EC_POINT_mul(group, point_mul_aGp, NULL, point_mul_aG, key_big, NULL);
//hex_pk = EC_POINT_point2hex(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, NULL);
EC_POINT_point2bn(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, key_big, NULL);
hex_pk = BN_bn2dec(key_big);
strCipher_list.push_back((std::string) hex_pk);
}
}
EC_GROUP_free(group);
EC_POINT_free(point_mul_aG);
EC_POINT_free(point_mul_aGp);
};
void myECC::decrypt(std::string key, std::vector<std::string> &plaintext, std::vector<std::string> &strCipher_list, unsigned long long size, int div) {
BIGNUM *key_big = BN_new();
BIGNUM *data_big = BN_new();
char *hex_pk;
BN_dec2bn(&key_big, (char *) key.data());//随机数转换成大数
//建立椭圆曲线
EC_KEY *ecdh = EC_KEY_new();
EC_GROUP *group;
EC_POINT *point_mul_aG, *point_mul_aGp;
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);//NID_secp521r1
group = (struct ec_group_st *) EC_KEY_get0_group(ecdh);
point_mul_aG = EC_POINT_new(group);
point_mul_aGp = EC_POINT_new(group);
//获得阶N
BIGNUM *order, *key_inverse;
order = BN_new();
key_inverse = BN_new();
EC_GROUP_get_order(group, order,NULL);
//求逆
BN_mod_inverse( key_inverse,key_big, order,NULL);
//EC_POINT_mul(group, point_mul_aG, NULL, generator, key_big, NULL);
if(div){
for (int i = 0; i < size; ++i) {
char *str_a = (char *) strCipher_list[i].data();
BN_dec2bn(&data_big, str_a);
EC_POINT_bn2point(group, data_big, point_mul_aG, NULL);
EC_POINT_mul(group, point_mul_aGp, NULL, point_mul_aG, key_inverse, NULL);
//hex_pk = EC_POINT_point2hex(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, NULL);
EC_POINT_point2bn(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, data_big, NULL);//将点转换成大数。
hex_pk = BN_bn2dec(data_big);//将大数转换成整数字符串。
plaintext.push_back(((std::string) hex_pk).substr(0, div));
}
} else{
for (int i = 0; i < size; ++i) {
char *str_a = (char *) strCipher_list[i].data();
BN_dec2bn(&data_big, str_a);
EC_POINT_bn2point(group, data_big, point_mul_aG, NULL);
EC_POINT_mul(group, point_mul_aGp, NULL, point_mul_aG, key_inverse, NULL);
//hex_pk = EC_POINT_point2hex(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, NULL);
EC_POINT_point2bn(group, point_mul_aGp, POINT_CONVERSION_COMPRESSED, data_big, NULL);//将点转换成大数。
hex_pk = BN_bn2dec(data_big);//将大数转换成整数字符串。
plaintext.push_back((std::string) hex_pk);
}
}
EC_GROUP_free(group);
EC_POINT_free(point_mul_aG);
EC_POINT_free(point_mul_aGp);
}
ECDH.h
//
// Created by admin on 2022/10/9.
//
#ifndef BPIR_ECDH_H
#define BPIR_ECDH_H
#include <openssl/pem.h>
#include <openssl/ecdh.h>
#include <iostream>
#include <sstream>
#include <vector>
namespace aes{}
class myECC {
public:
void encrypt(std::string key, std::vector<std::string> &plaintext, std::vector<std::string> &strCipher_list, unsigned long long size, int div = 0);
void decrypt(std::string key, std::vector<std::string> &plaintext, std::vector<std::string> &strCipher_list, unsigned long long size, int div = 0);
};
#endif //BPIR_ECDH_H