当前位置:   article > 正文

SM3WithSM2摘要的SM2签名验签

sm3withsm2

这个代码有可能不符合国标。。。

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <openssl/ssl.h>
  4. #include <openssl/err.h>
  5. #include <openssl/pem.h>
  6. #include <openssl/conf.h>
  7. #include <openssl/x509v3.h>
  8. #include <openssl/bn.h>
  9. #include <openssl/crypto.h>
  10. #include <openssl/evp.h>
  11. #include <openssl/ecdsa.h>
  12. #include <openssl/sha.h>
  13. #include <openssl/asn1.h>
  14. #include <openssl/x509.h>
  15. #include <openssl/objects.h>
  16. #include <openssl/buffer.h>
  17. #include <openssl/sm2.h>
  18. int hashForSM3(unsigned char* clearText, int clearTextLen, unsigned char* sm3Data){
  19. int ret = -1;
  20. //初始化摘要结构体
  21. EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
  22. if(!mdctx)
  23. return -1;
  24. EVP_MD_CTX_init(mdctx);
  25. //设置摘要算法和密码算法引擎
  26. if(!EVP_DigestInit_ex(mdctx, EVP_sm3(), NULL))
  27. goto ERR;
  28. //输入原文clearText
  29. if(!EVP_DigestUpdate(mdctx,clearText, clearTextLen))
  30. goto ERR;
  31. //输出摘要值,外部判断ret是否为32作为成功条件
  32. if(!EVP_DigestFinal(mdctx, sm3Data, (unsigned int*)&ret))
  33. goto ERR;
  34. ERR:
  35. EVP_MD_CTX_destroy(mdctx);
  36. return ret;
  37. }
  38. int hashForSM3WithSM2(unsigned char* clearText, int clearTextLen, unsigned char* puk, int pukLen, unsigned char* sm3Data){
  39. //以下为国密标准推荐参数,id="1234567812345678",长度是128bit0x0080
  40. unsigned char sm2_par_dig[210] = {//idlen[2]+id[16]+parm[128]+puk[64]
  41. 0x00,0x80,
  42. 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
  43. 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  44. 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,
  45. 0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,0x9E,0x4B,0xCF,0x65,0x09,0xA7,
  46. 0xF3,0x97,0x89,0xF5,0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94,0x0E,0x93,
  47. 0x32,0xC4,0xAE,0x2C,0x1F,0x19,0x81,0x19,0x5F,0x99,0x04,0x46,0x6A,0x39,0xC9,0x94,
  48. 0x8F,0xE3,0x0B,0xBF,0xF2,0x66,0x0B,0xE1,0x71,0x5A,0x45,0x89,0x33,0x4C,0x74,0xC7,
  49. 0xBC,0x37,0x36,0xA2,0xF4,0xF6,0x77,0x9C,0x59,0xBD,0xCE,0xE3,0x6B,0x69,0x21,0x53,
  50. 0xD0,0xA9,0x87,0x7C,0xC6,0x2A,0x47,0x40,0x02,0xDF,0x32,0xE5,0x21,0x39,0xF0,0xA0,
  51. };
  52. //对应规范pdf中的章节8.1
  53. memcpy(sm2_par_dig + 2 + 16 + 128, puk, pukLen);
  54. unsigned char* sm3_e = (unsigned char*)malloc(32 + clearTextLen);
  55. if(32 != hashForSM3(sm2_par_dig, 210, sm3_e)){
  56. free(sm3_e);
  57. return -1;
  58. }
  59. //对应规范pdf中的章节8.2
  60. memcpy(sm3_e + 32, clearText, clearTextLen);
  61. if(32 != hashForSM3(sm3_e, 32 + clearTextLen, sm3Data)){
  62. free(sm3_e);
  63. return -1;
  64. }
  65. free(sm3_e);
  66. return 0;
  67. }
  68. int main(){
  69. int i = 0;
  70. BIO *bio_pri = NULL;
  71. BIO *bio_puk = NULL;
  72. EVP_PKEY *pkey_pri = NULL;
  73. EC_KEY *prikey = NULL;
  74. EVP_PKEY *pkey_puk = NULL;
  75. EC_KEY *pubkey = NULL;
  76. X509 *cert = NULL;
  77. unsigned char* puk = NULL;
  78. int pukLen = 0;
  79. unsigned char* clearText = (unsigned char*)"1234567890123456";
  80. int clearTextLen = strlen((char*)clearText);
  81. unsigned char sm3Data[32] = {0};
  82. int sm3DataLen = 0;
  83. unsigned char out[1024] = {0};
  84. int outLen = 0;
  85. ///公钥相关结构
  86. //bio_puk = BIO_new_file("server_cert.der", "r");
  87. bio_puk = BIO_new_file("server_cert.pem", "r");
  88. if (!bio_puk) goto ERR;
  89. //cert = d2i_X509_bio(bio_puk, NULL);
  90. cert = PEM_read_bio_X509(bio_puk, NULL, NULL, NULL);
  91. if (!cert) goto ERR;
  92. pkey_puk = X509_get_pubkey(cert);
  93. if (!pkey_puk) goto ERR;
  94. pubkey = EVP_PKEY_get0_EC_KEY(pkey_puk);//don't free
  95. if (!pubkey) goto ERR;
  96. //要去除04标识
  97. pukLen = i2d_PublicKey(pkey_puk,(unsigned char**)&puk) - 1;
  98. if (!puk) goto ERR;
  99. ///私钥相关结构
  100. bio_pri = BIO_new_file("server_private.key", "r");
  101. if (!bio_pri) goto ERR;
  102. pkey_pri = PEM_read_bio_PrivateKey(bio_pri, NULL, NULL, NULL);
  103. if (!pkey_pri) goto ERR;
  104. prikey = EVP_PKEY_get0_EC_KEY(pkey_pri);//don't free
  105. if (!prikey) goto ERR;
  106. ///sm3 sm2 sign/verify
  107. if(hashForSM3WithSM2(clearText, clearTextLen, puk, pukLen, sm3Data))
  108. goto ERR;
  109. if (!SM2_sign(NID_undef, sm3Data, sm3DataLen, out, (unsigned int*)&outLen, prikey))
  110. goto ERR;
  111. printf("out[%d]:\n", outLen);
  112. for (int i = 0; i != outLen; i++) {
  113. printf("%02x ", *(out + i));
  114. if ((i != 0 && (i + 1) % 16 == 0) || i == outLen - 1) {
  115. printf("\n");
  116. }
  117. }
  118. printf("\n");
  119. FILE *fp_w = fopen("server_16.sig", "wb");
  120. for(int i=0; i < outLen; i++)
  121. {
  122. fwrite(((unsigned char*)(out+i)), 1, 1, fp_w);
  123. }
  124. fclose(fp_w);
  125. FILE *fp_r = fopen("server_16.sig", "rb");
  126. size_t slen = 0;
  127. fseek(fp_r, 0, SEEK_SET);
  128. int nRet;
  129. for(int i=0; ; i++)
  130. {
  131. nRet=fread(&(out[i]), 1, 1, fp_r);
  132. if(1 != nRet)
  133. {
  134. break;
  135. }
  136. printf("%02x ",out[i]);
  137. slen++;
  138. }
  139. fclose(fp_r);
  140. if (1 != SM2_verify(NID_undef, sm3Data, sm3DataLen, out, outLen, pubkey))
  141. goto ERR;
  142. printf("verify success\n");
  143. ERR:
  144. if(puk) OPENSSL_free(puk);
  145. if(bio_pri) BIO_free_all(bio_pri);
  146. if(bio_puk) BIO_free_all(bio_puk);
  147. if(pkey_pri) EVP_PKEY_free(pkey_pri);
  148. if(pkey_puk) EVP_PKEY_free(pkey_puk);
  149. if(cert) X509_free(cert);
  150. return 0;
  151. }

参考:

Gmssl实现SM2签名验签

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/118167
推荐阅读
相关标签
  

闽ICP备14008679号