ECC加密——C++/OPENssl实现

一、介绍:

因为最近设计一些密钥交换相关的协议,做了很多调研,和学习。本来想直接使用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 &plaintext, std::vector &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 &plaintext, std::vector &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 
#include 
#include 
#include 
#include 
namespace aes{}
class myECC {
public:
    void encrypt(std::string key, std::vector &plaintext, std::vector &strCipher_list, unsigned long long size,  int div = 0);
    void decrypt(std::string key, std::vector &plaintext, std::vector &strCipher_list, unsigned long long size,  int div = 0);
};


#endif //BPIR_ECDH_H

你可能感兴趣的:(PSI,安全)