当前位置:   article > 正文

gmssl国密sm2(生成密钥对-私钥签字-证书验签)_gmssl sm2身份验证

gmssl sm2身份验证

生成密钥对:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include "e_os.h"
  5. #include "sm2ToOC.h"
  6. #include "string.h"
  7. # include <openssl/bn.h>
  8. # include <openssl/ec.h>
  9. # include <openssl/evp.h>
  10. # include <openssl/rand.h>
  11. # include <openssl/engine.h>
  12. # include <openssl/sm2.h>
  13. # include "sm2_lcl.h"
  14. # include "pkcs12.h"
  15. #include <openssl/pem.h>
  16. #include "ec/ec_lcl.h"
  17. #include "bn/bn_lcl.h"
  18. int genkey()
  19. {
  20. EC_KEY *keypair = NULL;
  21. EC_GROUP *group1 = NULL;
  22. keypair = EC_KEY_new();
  23. if(!keypair) {
  24. printf("Failed to Gen Key");
  25. exit(1);
  26. }
  27. group1 = EC_GROUP_new_by_curve_name(NID_sm2p256v1);
  28. if(group1 == NULL){
  29. printf("Failed to Gen Key");
  30. exit(1);
  31. }
  32. int ret1 = EC_KEY_set_group(keypair, group1);
  33. if(ret1 != 1){
  34. printf("Failed to Gen Key");
  35. exit(1);
  36. }
  37. int ret2 = EC_KEY_generate_key(keypair);
  38. if(ret2 != 1){
  39. printf("Failed to Gen Key");
  40. exit(1);
  41. }
  42. size_t pri_len;
  43. size_t pub_len;
  44. char *pri_key = NULL;
  45. char *pub_key = NULL;
  46. BIO *pri = BIO_new(BIO_s_mem());
  47. BIO *pub = BIO_new(BIO_s_mem());
  48. PEM_write_bio_ECPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
  49. PEM_write_bio_EC_PUBKEY(pub, keypair);
  50. BIO *bio_out = BIO_new_file("private.key", "w");
  51. PEM_write_bio_ECPrivateKey(bio_out, keypair, NULL, NULL, 0, NULL, NULL);
  52. BIO_free(bio_out);
  53. bio_out = BIO_new_file("public.key", "w");
  54. PEM_write_bio_EC_PUBKEY(bio_out, keypair);
  55. BIO_free(bio_out);
  56. pri_len = BIO_pending(pri);
  57. pub_len = BIO_pending(pub);
  58. pri_key = (char *)malloc(pri_len + 1);
  59. pub_key = (char *)malloc(pub_len + 1);
  60. BIO_read(pri, pri_key, pri_len);
  61. BIO_read(pub, pub_key, pub_len);
  62. pri_key[pri_len] = '\0';
  63. pub_key[pub_len] = '\0';
  64. EC_KEY_free(keypair);
  65. BIO_free_all(pub);
  66. BIO_free_all(pri);
  67. free(pri_key);
  68. free(pub_key);
  69. return 1;
  70. }
  71. void main(void)
  72. {
  73. genkey();
  74. }

签字验签:

  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. #include <apps/apps.h>
  19. int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
  20. {
  21. BIO *mem;
  22. int len, ret;
  23. unsigned char tbuf[1024];
  24. mem = BIO_new(BIO_s_mem());
  25. if (mem == NULL)
  26. return -1;
  27. for (;;) {
  28. if ((maxlen != -1) && maxlen < 1024)
  29. len = maxlen;
  30. else
  31. len = 1024;
  32. len = BIO_read(in, tbuf, len);
  33. if (len < 0) {
  34. BIO_free(mem);
  35. return -1;
  36. }
  37. if (len == 0)
  38. break;
  39. if (BIO_write(mem, tbuf, len) != len) {
  40. BIO_free(mem);
  41. return -1;
  42. }
  43. maxlen -= len;
  44. if (maxlen == 0)
  45. break;
  46. }
  47. ret = BIO_get_mem_data(mem, (char **)out);
  48. BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
  49. BIO_free(mem);
  50. return ret;
  51. }
  52. static int sm2utl_sign(const EVP_MD *md, BIO *in, BIO *out, const char *id,
  53. ENGINE *e, EC_KEY *ec_key, int sign)
  54. {
  55. int ret = 0;
  56. EVP_MD_CTX *md_ctx = NULL;
  57. ECDSA_SIG *sig = NULL;
  58. unsigned char buf[1024];
  59. size_t siz = sizeof(buf);
  60. unsigned int ulen = sizeof(buf);
  61. int len;
  62. printf("sm2utl_sign\n");
  63. if (!(md_ctx = EVP_MD_CTX_new())
  64. || !EVP_DigestInit_ex(md_ctx, md, e)
  65. || !SM2_compute_id_digest(md, id, strlen(id), buf, &siz, ec_key)
  66. || !EVP_DigestUpdate(md_ctx, buf, siz)) {
  67. }
  68. while ((len = BIO_read(in, buf, sizeof(buf))) > 0) {
  69. if (!EVP_DigestUpdate(md_ctx, buf, len)) {
  70. }
  71. }
  72. if (!EVP_DigestFinal_ex(md_ctx, buf, &ulen)) {
  73. }
  74. len = (int)ulen;
  75. if (sign) {
  76. unsigned char *p = buf;
  77. if (!(sig = SM2_do_sign(buf, len, ec_key))
  78. || (len = i2d_ECDSA_SIG(sig, &p)) <= 0) {
  79. }
  80. }
  81. if (BIO_write(out, buf, len) != len) {
  82. }
  83. ret = 1;
  84. end:
  85. EVP_MD_CTX_free(md_ctx);
  86. ECDSA_SIG_free(sig);
  87. return ret;
  88. }
  89. static int sm2utl_verify(const EVP_MD *md, BIO *in, BIO *out, BIO *sig,
  90. const char *id, ENGINE *e, EC_KEY *ec_key)
  91. {
  92. int ret = 0;
  93. EVP_MD_CTX *md_ctx = NULL;
  94. unsigned char *sigbuf = NULL;
  95. unsigned char buf[1024];
  96. size_t siz = sizeof(buf);
  97. unsigned int ulen = sizeof(buf);
  98. int siglen, len;
  99. siglen = bio_to_mem(&sigbuf, 256, sig);
  100. if (siglen < 0) {
  101. }
  102. if (!(md_ctx = EVP_MD_CTX_new())
  103. || !EVP_DigestInit_ex(md_ctx, md, e)
  104. || !SM2_compute_id_digest(md, id, strlen(id), buf, &siz, ec_key)
  105. || !EVP_DigestUpdate(md_ctx, buf, siz)) {
  106. }
  107. while ((len = BIO_read(in, buf, sizeof(buf))) > 0) {
  108. if (!EVP_DigestUpdate(md_ctx, buf, len)) {
  109. }
  110. }
  111. siz = sizeof(buf);
  112. if (!EVP_DigestFinal_ex(md_ctx, buf, &ulen)) {
  113. }
  114. /* SM2_verify() can check no suffix on signature */
  115. ret = SM2_verify(NID_undef, buf, ulen, sigbuf, siglen, ec_key);
  116. if (ret == 1) {
  117. printf("Signature Verification Successful\n");
  118. } else {
  119. printf("Signature Verification Failure\n");
  120. ret = 0;
  121. }
  122. end:
  123. OPENSSL_free(sigbuf);
  124. EVP_MD_CTX_free(md_ctx);
  125. return ret;
  126. }
  127. int signature(char *msg)
  128. {
  129. BIO *in = NULL, *out = NULL, *sig = NULL;
  130. char *keyfile = NULL;
  131. EVP_PKEY *pkey = NULL;
  132. EC_KEY *ec_key = NULL;
  133. int keyform = FORMAT_PEM;
  134. const EVP_MD *md = EVP_sm3();
  135. in = BIO_new_file("text.txt", "rb");
  136. out = BIO_new_file("text.sig", "wb");
  137. BIO * key = NULL;
  138. key = BIO_new_file("private.key", "r");
  139. pkey=PEM_read_bio_PrivateKey(key, NULL, 0, NULL);
  140. if (!(ec_key = EVP_PKEY_get0_EC_KEY(pkey))
  141. || !EC_KEY_is_sm2p256v1(ec_key)) {
  142. printf("Invalid key type\n");
  143. return -1;
  144. }
  145. sm2utl_sign(md, in, out, "1234567812345678", 0, ec_key, 1);
  146. return 1;
  147. }
  148. int verify_sig(void)
  149. {
  150. const EVP_MD *md = EVP_sm3();
  151. BIO *in = NULL, *out = NULL, *sig = NULL;
  152. in = BIO_new_file("text.txt", "rb");
  153. sig = BIO_new_file("text_1.sig", "rb");
  154. //FILE *fp = fopen("public_cert.pem", "r");
  155. //X509 *cert = PEM_read_X509(fp, NULL, NULL, NULL);
  156. FILE *fp = fopen("public.cer", "r");
  157. X509 *cert = d2i_X509_fp(fp, NULL);
  158. EVP_PKEY *evk = X509_get_pubkey(cert);
  159. EC_KEY *ec_key=EVP_PKEY_get0_EC_KEY(evk);
  160. if (1==sm2utl_verify(md, in, out, sig, "1234567812345678", 0, ec_key))
  161. {
  162. printf("verify success\n");
  163. }
  164. else
  165. {
  166. printf("verify fail\n");
  167. }
  168. return 1;
  169. }
  170. void main(void)
  171. {
  172. signature("1234567890123456");
  173. //verify_sig();
  174. }

SM2签名及验证过程中,并不是直接计算被签名数据的摘要,而是要经过专门的预处理过程得到摘要。此过程包含两个阶段的摘要计算:

1)Z = SM3(ENTL || ID || a || b || x_G || y_G || x_A || y_A)

ENTL || ID || a || b || x_G || y_G || x_A || y_A表示签名元素数据的拼接(级联)。

其中,ENTL 是签名者 ID 的位长度,占两个字节;ID是签名者ID,国密标准里定义的缺省签名者ID用UFT_8字符串表示是“1234567812345678”,用十六进制表示是0x31323334353637383132333435363738。所以在缺省情况下,ENTL值是0x0080.a, b, x_G, y_G 都是SM2算法标准中给定的值。a和b是椭圆曲线y=x+ax+b的系数,x_G, y_G是SM2算法选定的基点的坐标。上述参数都是固定值:a=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC

b=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93

x_G= 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7

y_G=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0

x_A || y_A就是公钥两部分值的拼接,注意,没有0x04的部分;将上述各元素拼接值进行SM3运算,得到结果Z。2) H=SM3(Z || M)

Z是第一步运算得到的摘要,M是签名的原文,将两者拼接,再进行SM3摘要运算。得到的摘要就是预处理得到的结果,将用于后续的签名及验证运算。

参考:

基于Gmssl的SM2加解密算法Demo - 程序员大本营
GitHub - guanzhi/GmSSL: 支持国密SM2/SM3/SM4/SM9/SSL的密码工具箱

百度安全验证

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

闽ICP备14008679号