SM2算法第十五篇:ECDSA数字签名算法的C语言实现

代码

#include <string.h>

#include <stdio.h>

#include <openssl/ec.h>

#include <openssl/ssl.h>

#include <openssl/ecdsa.h>

#include <openssl/objects.h>

#include <openssl/err.h>

 

int    main()

{

       EC_KEY              *key1,*key2;

       EC_POINT            *pubkey1,*pubkey2;

       EC_GROUP            *group1,*group2;

       int                 ret,nid,size,i,sig_len;

       unsigned char*      signature,digest[20];

       BIO                 *berr;

       EC_builtin_curve    *curves;

       int                 crv_len;

       char                shareKey1[128],shareKey2[128];

       int                 len1,len2;

 

       /* 构造EC_KEY数据结构 */

       key1=EC_KEY_new();

       if(key1==NULL)

       {

              printf("EC_KEY_new err!\n");

              return -1;

       }

       key2=EC_KEY_new();

       if(key2==NULL)

       {

     
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
SM2算法是一种基于椭圆曲线密码体制的公钥密码算法,广泛应用于数字签名、身份认证、密钥协商等场景。在C语言实现SM2算法需要借助一些常用的密码学库,例如OpenSSL、libgcrypt等。以下是一个使用OpenSSL库实现SM2算法的示例代码: ``` #include <openssl/ec.h> #include <openssl/ecdsa.h> #include <openssl/evp.h> #include <openssl/rand.h> #include <openssl/bn.h> #define SM2_NID NID_sm2 #define SM2_PUBKEY_SIZE 65 #define SM2_PRIVKEY_SIZE 32 int sm2_gen_keypair(unsigned char *pubkey, unsigned char *privkey) { EC_KEY *ec_key = EC_KEY_new_by_curve_name(SM2_NID); if (ec_key == NULL) { return -1; } if (!EC_KEY_generate_key(ec_key)) { EC_KEY_free(ec_key); return -1; } const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key); const EC_POINT *ec_pubkey = EC_KEY_get0_public_key(ec_key); const BIGNUM *ec_privkey = EC_KEY_get0_private_key(ec_key); size_t pubkey_len = EC_POINT_point2oct(ec_group, ec_pubkey, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); unsigned char *tmp_pubkey = malloc(pubkey_len); if (tmp_pubkey == NULL) { EC_KEY_free(ec_key); return -1; } if (EC_POINT_point2oct(ec_group, ec_pubkey, POINT_CONVERSION_UNCOMPRESSED, tmp_pubkey, pubkey_len, NULL) != pubkey_len) { free(tmp_pubkey); EC_KEY_free(ec_key); return -1; } memcpy(pubkey, tmp_pubkey + 1, SM2_PUBKEY_SIZE); memcpy(privkey, ec_privkey, SM2_PRIVKEY_SIZE); free(tmp_pubkey); EC_KEY_free(ec_key); return 0; } int sm2_sign(const unsigned char *msg, size_t msg_len, const unsigned char *privkey, unsigned char *signature) { EC_KEY *ec_key = EC_KEY_new_by_curve_name(SM2_NID); if (ec_key == NULL) { return -1; } BIGNUM *ec_privkey = BN_bin2bn(privkey, SM2_PRIVKEY_SIZE, NULL); if (ec_privkey == NULL) { EC_KEY_free(ec_key); return -1; } if (!EC_KEY_set_private_key(ec_key, ec_privkey)) { BN_clear_free(ec_privkey); EC_KEY_free(ec_key); return -1; } const EVP_MD *md = EVP_sm3(); if (md == NULL) { BN_clear_free(ec_privkey); EC_KEY_free(ec_key); return -1; } unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; if (!EVP_Digest(msg, msg_len, digest, &digest_len, md, NULL)) { BN_clear_free(ec_privkey); EC_KEY_free(ec_key); return -1; } ECDSA_SIG *ec_sig = ECDSA_do_sign(digest, digest_len, ec_key); if (ec_sig == NULL) { BN_clear_free(ec_privkey); EC_KEY_free(ec_key); return -1; } BIGNUM *r = NULL; BIGNUM *s = NULL; ECDSA_SIG_get0(ec_sig, (const BIGNUM **)&r, (const BIGNUM **)&s); int ret = 0; if (BN_bn2binpad(r, signature + 0, SM2_PRIVKEY_SIZE) != SM2_PRIVKEY_SIZE || BN_bn2binpad(s, signature + SM2_PRIVKEY_SIZE, SM2_PRIVKEY_SIZE) != SM2_PRIVKEY_SIZE) { ret = -1; } BN_clear_free(ec_privkey); ECDSA_SIG_free(ec_sig); EC_KEY_free(ec_key); return ret; } int sm2_verify(const unsigned char *msg, size_t msg_len, const unsigned char *pubkey, const unsigned char *signature) { EC_KEY *ec_key = EC_KEY_new_by_curve_name(SM2_NID); if (ec_key == NULL) { return -1; } const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key); const EVP_MD *md = EVP_sm3(); if (md == NULL) { EC_KEY_free(ec_key); return -1; } unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; if (!EVP_Digest(msg, msg_len, digest, &digest_len, md, NULL)) { EC_KEY_free(ec_key); return -1; } EC_POINT *ec_pubkey = EC_POINT_new(ec_group); if (ec_pubkey == NULL) { EC_KEY_free(ec_key); return -1; } if (!EC_POINT_oct2point(ec_group, ec_pubkey, pubkey, SM2_PUBKEY_SIZE, NULL)) { EC_POINT_free(ec_pubkey); EC_KEY_free(ec_key); return -1; } ECDSA_SIG *ec_sig = ECDSA_SIG_new(); if (ec_sig == NULL) { EC_POINT_free(ec_pubkey); EC_KEY_free(ec_key); return -1; } BIGNUM *r = BN_bin2bn(signature + 0, SM2_PRIVKEY_SIZE, NULL); BIGNUM *s = BN_bin2bn(signature + SM2_PRIVKEY_SIZE, SM2_PRIVKEY_SIZE, NULL); int ret = 0; if (r == NULL || s == NULL || !ECDSA_SIG_set0(ec_sig, r, s) || !ECDSA_do_verify(digest, digest_len, ec_sig, ec_pubkey)) { ret = -1; } BN_clear_free(r); BN_clear_free(s); ECDSA_SIG_free(ec_sig); EC_POINT_free(ec_pubkey); EC_KEY_free(ec_key); return ret; } ``` 此代码使用了OpenSSL库的EC模块和ECDSA模块实现SM2算法的密钥生成、签名和验证功能。在使用之前需要先安装OpenSSL库并链接到编译器中。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值