签名原理https://blog.youkuaiyun.com/Asia_ZhangQQ/article/details/96854514这个文章有详细说明,这里就不再说了,直接上源码
1.格式转换,OpenSSL EVP签名用到公私钥格式EVP_PKEY,先转成对应格式.如果是用EVP直接生成公私钥那就直接用EVP_PKEY 忽略掉这一步.
EVP_PKEY *pKey = EVP_PKEY_new();
sm2CreateEVP_PKEY(privateKey, 0, &pKey);
具体string 转EVP_PKEY,或者EC_KEY转EVP_PKEY后期再写个文章
2.EVP_PKEY_set_alias_type(pKey, EVP_PKEY_SM2);
设置公私钥类型为sm2曲线类型
The B structure will default to using ECDSA for signatures when it is
created. It should be set to B by calling:
3.签名初始化
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pKey, NULL);
When calling the EVP_DigestSignInit() or EVP_DigestVerifyInit() functions, a
pre-allocated B should be assigned to the B. This is
done by calling:
EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
设置signId,默认1234567812345678(java bc)可自定义"",数字,邮箱等
EVP_PKEY_CTX_set1_id(pctx, userAid, strlen(userAid));
ret = EVP_DigestSignInit(mctx, &pctx, EVP_sm3(), NULL,pKey);
4.操作签名明文
EVP_DigestSignUpdate(mctx, msg, msg_len);
5.签名
获取签名长度,这一段可不要,但是就无法知道签名长度,接收签名可能内容丢失,或者分配内存过大浪费
ret = EVP_DigestSignFinal(mctx, NULL, &sig_len);
ret = EVP_DigestSignFinal(mctx, sign, &sig_len);
至此签名完成,验签就是改下api
ret = EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pKey);
EVP_DigestVerifyUpdate(mctx, plaintext, plaintextDataLength);
int EVP_DigestVerify(EVP_MD_CTX *mctx, const unsigned char *sigret,
ret = EVP_DigestVerifyFinal(mctx, sign, signLength);
注意点:
1.公私钥生成,签名验签失败.公私钥是否符合格式.java bc库只能接收pkcs8私钥,OpenSSL都可以
2.签名完成,java bc库不能只能用,必须base64.一般base64 不行得使用OpenSSL base64 见如下文章
https://blog.youkuaiyun.com/yasi_xi/article/details/9040793
(之前写的没保存尴尬了)