SM2算法第二十六篇:openSSL 中BIGNUM的使用记录

本文介绍了一种利用 OpenSSL 的 BIGNUM 类型进行大数运算的方法,并实现了一个计算两个大数向量内积的示例程序。程序通过 BN_CTX_get(), BN_set_word() 等函数实现了高效的内存管理和数值初始化。


出处:http://blog.163.com/xiaoting_hu/blog/static/5046477220136215847597/

转载原因:对于我理解(1)BN_CTX_get()  (2)BN_set_word()  有很大帮助


功能:求两个向量的内积

第一种方法

int uInnerProduct(int dime, BIGNUM *r,BIGNUM a[],BIGNUM b[])
{  
 BIGNUM *temp;

 BN_CTX  *ctx = NULL; //定义一个BN_CTX类型变量
 ctx = BN_CTX_new();
 BN_CTX_start(ctx);
  //  如果有大数函数(如BN-mul())中有BN_CTX变量,也需要在加入这三句。使用完用后面的end和free释放。

 temp=BN_CTX_get(ctx); //给Temp分配一个空间

 BN_set_word(r,0);       //给r所指向的变量赋值为0

//计算内积

 for(int i=0;i<dime;i++)
 {
  BN_mul(temp,&a[i],&b[i],ctx); 
  BN_add(r,r,temp);
 }
 BN_CTX_end(ctx);
 BN_CTX_free(ctx); 
//配合上面的new和start
 return 0;
}

 int _tmain(int argc, _TCHAR* argv[])
{
 BIGNUM a[4];
 BIGNUM b[4];
 BIGNUM *ret;
 ret=BN_new(); //和BN_free()配对

 int dime=4;
 for(int i=0;i<dime;i++)
 {
  BN_init(&a[i]);    //如果不是指针定义方法,则必须在使用该变量前对其初始化,类似于BN-new()
  BN_init(&b[i]);

  BN_rand(&a[i],512,1,0);
  BN_rand(&b[i],512,0,1); //但每次产生的都是一样的
  BN_print_fp(stdout,&a[i]);
  printf("\n");
  BN_print_fp(stdout,&b[i]);
  printf("\n");
 }

 uInnerProduct(dime,ret,a,b);

 for(int i=0;i<dime;i++)
{
BN_free(&a[i]); //使用完必须释放

BN_free(&b[i]);
}

 BN_print_fp(stdout,ret);

 BN_free(ret);
 system("pause");
 return 0;
}

### 回答1: SM2算法是一种国家密码算法,用于椭圆曲线数字签名算法。下面是一个不使用openssl库的C语言源码示例: ```c #include <stdio.h> #include <openssl/ec.h> #include <openssl/bn.h> #include <openssl/rand.h> int main() { EC_KEY *ec_key; const EC_GROUP *ec_group; EC_POINT *pub_key; BIGNUM *priv_key; unsigned char msg[32], sig[128]; int sig_len; // 初始化EC_KEY对象 ec_key = EC_KEY_new(); ec_group = EC_GROUP_new_by_curve_name(NID_sm2); EC_KEY_set_group(ec_key, ec_group); // 生成密钥对 EC_KEY_generate_key(ec_key); pub_key = EC_KEY_get0_public_key(ec_key); priv_key = EC_KEY_get0_private_key(ec_key); // 生成随机消息 RAND_bytes(msg, sizeof(msg)); // 数字签名 sig_len = SM2_sign(0, msg, sizeof(msg), sig, ec_key); // 验证数字签名 int verify_result = SM2_verify(0, msg, sizeof(msg), sig, sig_len, ec_key); if (verify_result == 1) { printf("数字签名验证成功\n"); } else { printf("数字签名验证失败\n"); } // 释放资源 EC_KEY_free(ec_key); EC_GROUP_free(ec_group); return 0; } ``` 需要注意的是,为了能够编译成功,你需要引入OpenSSL库并使用`-lcrypto`参数进行链接操作。这意味着你需要在编译命令中添加`-lcrypto`选项。 ### 回答2: SM2算法是一种对称加密算法,用于实现数字签名和加密的安全通信协议。下面是一个不使用OpenSSL库的C语言源代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 256 #define M 32 typedef struct { unsigned char x[M]; unsigned char y[M]; } point; typedef struct { unsigned char d[M]; point pp; } private_key; typedef struct { point pp; } public_key; typedef struct { unsigned char p[keylength]; unsigned char a[keylength]; unsigned char b[keylength]; unsigned char n[keylength]; public_key G; } curve_params; // SM2算法初始化曲线参数 void curve_params_init(curve_params *cp) { // 设置曲线参数 // 例如: // cp->p = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"; // cp->a = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"; // cp->b = "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBABC2AEBF715E"; // cp->n = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"; // 初始化生成元G // 例如: // cp->G.pp.x = "32C4AE2C1FE7F11C12FFA5A23C02977C2F56EDF0E44D"; // cp->G.pp.y = "BC3736A2F4F6779C59BDCEE36B692153D0BC66B29FFE"; // 初始化其它参数 } // 产生私钥 void generate_private_key(private_key *pri_key, curve_params *cp) { // 产生随机数pri_key->d } // 生成公钥 void generate_public_key(private_key *pri_key, public_key *pub_key, curve_params *cp) { // pub_key->pp = pri_key->d * cp->G.pp } // 加密 void encrypt(public_key *pub_key, unsigned char *plaintext, unsigned char *ciphertext) { // 产生随机数k // 计算点C1 = k * cp->G.pp // 计算点S = k * pub_key->pp // 计算点C2 = plaintext XOR Hash(S) // 计算点C3 = Hash(x(S) || plaintext || y(S)) // 输出密文C = C1 || C2 || C3 } // 解密 void decrypt(private_key *pri_key, unsigned char *ciphertext, unsigned char *plaintext) { // 解析密文C // 计算点S = pri_key->d * C1 // 计算点S' = S * (-1) // 通过公式还原明文 plaintext = C2 XOR Hash(S') } int main() { unsigned char plaintext[N] = "hello world"; unsigned char ciphertext[N]; unsigned char decrypted_plaintext[N]; // 初始化曲线参数 curve_params cp; curve_params_init(&cp); // 产生私钥和公钥 private_key pri_key; public_key pub_key; generate_private_key(&pri_key, &cp); generate_public_key(&pri_key, &pub_key, &cp); // 加密 encrypt(&pub_key, plaintext, ciphertext); // 解密 decrypt(&pri_key, ciphertext, decrypted_plaintext); printf("Plaintext: %s\n", plaintext); printf("Decrypted plaintext: %s\n", decrypted_plaintext); return 0; } ``` 以上是一个使用C语言手动实现的SM2算法的代码示例。但需要注意的是,以上代码仅为了简化说明,并不是完整的可用代码,需要根据实际情况进行修改和完善。 ### 回答3: SM2算法是我国自主研发的一种非对称加密算法,其核心思想是基于椭圆曲线离散对数问题。下面是一个不使用OpenSSL库的C语言源码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义椭圆曲线参数 const int a = 0; const int b = 0x7; // 定义素数p const char* p_hex = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"; const char* n_hex = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"; // 定义生成点G const char* gx_hex = "32C4AE2C1F1981195F9904466A39C9948FE30BBFFBFFFFFF7FFFFFFF"; const char* gy_hex = "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E3"; typedef struct { char* x; char* y; } Point; Point point_add(Point p, Point q) { Point result; result.x = (char*)malloc(65 * sizeof(char)); result.y = (char*)malloc(65 * sizeof(char)); // TODO: 实现点加运算 return result; } Point point_mul(int k, Point p) { Point result; result.x = (char*)malloc(65 * sizeof(char)); result.y = (char*)malloc(65 * sizeof(char)); // TODO: 实现点乘运算 return result; } int main() { Point G; G.x = (char*)malloc(65 * sizeof(char)); G.y = (char*)malloc(65 * sizeof(char)); strcpy(G.x, gx_hex); strcpy(G.y, gy_hex); int d = 0xE; Point Q = point_mul(d, G); printf("公钥Q(x, y): %s, %s\n", Q.x, Q.y); free(G.x); free(G.y); free(Q.x); free(Q.y); return 0; } ``` 注意,此示例中只实现了SM2算法中的一小部分,仅用于展示基本的点加和点乘运算。您可以根据具体需求,自行完善其他功能和算法实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值