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<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

ECC(Elliptic Curve Cryptography)加密算法的C语言实现可以通过使用一些开的密码库来完成。一个为使用的密码库是OpenSSL,它提供了对ECC算法的支持。以下是一个示例代码,展示了如何使用OpenSSL库来实现ECC加密算法的C语言代码: ```c #include <stdio.h> #include <openssl/ec.h> #include <openssl/evp.h> #include <openssl/rand.h> #include <openssl/sha.h> int main() { // 初始化 OpenSSLOpenSSL_add_all_algorithms(); // 创建 ECC 密钥对 EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); EC_KEY_generate_key(key); // 获取公钥和私钥 const EC_POINT *public_key = EC_KEY_get0_public_key(key); const BIGNUM *private_key = EC_KEY_get0_private_key(key); // 打印公钥和私钥 char *public_key_hex = EC_POINT_point2hex(EC_KEY_get0_group(key), public_key, POINT_CONVERSION_UNCOMPRESSED, NULL); char *private_key_hex = BN_bn2hex(private_key); printf("公钥: %s\n", public_key_hex); printf("私钥: %s\n", private_key_hex); // 释放内存 OPENSSL_free(public_key_hex); OPENSSL_free(private_key_hex); EC_KEY_free(key); // 清理 OpenSSL 库 EVP_cleanup(); return 0; } ``` 这段代码使用了OpenSSL库中的函数来创建一个椭圆曲线密钥对,并打印出生成的公钥和私钥。你可以将这段代码保存为一个C文件,然后使用gcc编译器来编译并执行。 请注意,这只是一个简单的示例,实际上ECC加密算法涉及到更多的细节和安全性考虑。在实际应用中,你可能需要进一步了解ECC算法的具体实现细节,并根据自己的需求进行适当的修改和扩展。同时,确保你的代码实现符合密码学安全标准,并考虑到安全性方面的最佳实践。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值