GB35114---基于openssl加密库进行开发(二)
接上篇GB35114---基于openssl加密庫(kù)進(jìn)行開(kāi)發(fā)(一)
-----------------------------------------------------------------------------------------------------------------------------
openssl的兩個(gè).so動(dòng)態(tài)庫(kù)libcrypto.so.1.1 and?libssl.so.1.1不能直接調(diào)用sm2簽名及加密函數(shù)。
但是它里面集成了sm2的橢圓曲線,那我們就根據(jù)sm2曲線算法直接寫(xiě)個(gè)簽名函數(shù)。
其實(shí)在openssl的sm2_sign.c內(nèi)已經(jīng)有相關(guān)算法,那我們就伸手了。
BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,const EC_KEY *key,const uint8_t *id,const int id_len,const uint8_t *msg, int msg_len) {EVP_MD_CTX *hash = EVP_MD_CTX_new();const int md_size = EVP_MD_size(digest);uint8_t *z = NULL;BIGNUM *e = NULL;if (md_size < 0) {goto done;}z = OPENSSL_zalloc(md_size);if (hash == NULL || z == NULL) {goto done;}if (!sm2_compute_z_digest(z, digest, id, id_len, key)) {/* SM2err already called */goto done;}if (!EVP_DigestInit(hash, digest)|| !EVP_DigestUpdate(hash, z, md_size)|| !EVP_DigestUpdate(hash, msg, msg_len)/* reuse z buffer to hold H(Z || M) */|| !EVP_DigestFinal(hash, z, NULL)) {goto done;}e = BN_bin2bn(z, md_size, NULL);if (e == NULL)done:OPENSSL_free(z);EVP_MD_CTX_free(hash);return e; }static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) {const BIGNUM *dA = EC_KEY_get0_private_key(key);const EC_GROUP *group = EC_KEY_get0_group(key);const BIGNUM *order = EC_GROUP_get0_order(group);ECDSA_SIG *sig = NULL;EC_POINT *kG = NULL;BN_CTX *ctx = NULL;BIGNUM *k = NULL;BIGNUM *rk = NULL;BIGNUM *r = NULL;BIGNUM *s = NULL;BIGNUM *x1 = NULL;BIGNUM *tmp = NULL;kG = EC_POINT_new(group);ctx = BN_CTX_new();if (kG == NULL || ctx == NULL) {goto done;}BN_CTX_start(ctx);k = BN_CTX_get(ctx);rk = BN_CTX_get(ctx);x1 = BN_CTX_get(ctx);tmp = BN_CTX_get(ctx);if (tmp == NULL) {goto done;}/** These values are returned and so should not be allocated out of the* context*/r = BN_new();s = BN_new();if (r == NULL || s == NULL) {goto done;}for (;;) {if (!BN_priv_rand_range(k, order)) {goto done;}if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)|| !EC_POINT_get_affine_coordinates(group, kG, x1, NULL,ctx)|| !BN_mod_add(r, e, x1, order, ctx)) {goto done;}/* try again if r == 0 or r+k == n */if (BN_is_zero(r))continue;if (!BN_add(rk, r, k)) {goto done;}if (BN_cmp(rk, order) == 0)continue;if (!BN_add(s, dA, BN_value_one())|| !ec_group_do_inverse_ord(group, s, s, ctx)|| !BN_mod_mul(tmp, dA, r, order, ctx)|| !BN_sub(tmp, k, tmp)|| !BN_mod_mul(s, s, tmp, order, ctx)) {goto done;}sig = ECDSA_SIG_new();if (sig == NULL) {goto done;}/* takes ownership of r and s */ECDSA_SIG_set0(sig, r, s);break;}done:if (sig == NULL) {BN_free(r);BN_free(s);}BN_CTX_free(ctx);EC_POINT_free(kG);return sig; }ECDSA_SIG *sm2_do_sign(const EC_KEY *key,const EVP_MD *digest,const uint8_t *id,const int id_len,const uint8_t *msg, int msg_len) {BIGNUM *e = NULL;ECDSA_SIG *sig = NULL;e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);if (e == NULL) {/* SM2err already called */goto done;}sig = sm2_sig_gen(key, e);done:BN_free(e);return sig; }其中
sm2_compute_msg_hash? ?函數(shù)是對(duì)簽名數(shù)據(jù)進(jìn)行hash散列;
sm2_sig_gen? ?函數(shù)是SM2簽名算法,注:該函數(shù)最后調(diào)用ECDSA_SIG_set0(sig, r, s)對(duì)SM2真正的簽名的r跟s進(jìn)行了轉(zhuǎn)化,返回ECDSA_SIG結(jié)構(gòu)的簽名數(shù)據(jù)。
至此SM2-SM3的簽名函數(shù)就搞定了,我們依葫蘆畫(huà)瓢完成驗(yàn)簽、加解密等函數(shù)。
最后附上可用的代碼,也是我過(guò)gb35114的加密代碼。
SM2-SM3示例代碼
?
有錯(cuò)誤請(qǐng)留言,謝謝
下篇
GB35114---聊聊SM2簽名格式
---bob? 2020/3/17 10.44
總結(jié)
以上是生活随笔為你收集整理的GB35114---基于openssl加密库进行开发(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用Python批量转换图片格式
- 下一篇: 一款软件测试脚本生成工具