gmssl National Secret sm2(鍵ペアの生成-秘密鍵署名-証明書の検証)

キーペアを生成します。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "e_os.h"
#include "sm2ToOC.h"
#include "string.h"
# include <openssl/bn.h>
# include <openssl/ec.h>
# include <openssl/evp.h>
# include <openssl/rand.h>
# include <openssl/engine.h>
# include <openssl/sm2.h>
# include "sm2_lcl.h"
# include "pkcs12.h"
#include <openssl/pem.h>
#include "ec/ec_lcl.h"
#include "bn/bn_lcl.h"

int genkey()
{
    EC_KEY *keypair = NULL;
    EC_GROUP *group1 = NULL;

    keypair = EC_KEY_new();
    if(!keypair) {
        printf("Failed to Gen Key");
        exit(1);
    }

    group1 = EC_GROUP_new_by_curve_name(NID_sm2p256v1);

    if(group1 == NULL){
        printf("Failed to Gen Key");
        exit(1);
    }

    int ret1 = EC_KEY_set_group(keypair, group1);
    if(ret1 != 1){
        printf("Failed to Gen Key");
        exit(1);
    }

    int ret2 = EC_KEY_generate_key(keypair);
    if(ret2 != 1){
        printf("Failed to Gen Key");
        exit(1);
    }

    size_t pri_len;
    size_t pub_len;
    char *pri_key = NULL;
    char *pub_key = NULL;
 
	BIO *pri = BIO_new(BIO_s_mem());
	BIO *pub = BIO_new(BIO_s_mem());
 
	PEM_write_bio_ECPrivateKey(pri, keypair, NULL, NULL, 0, NULL, NULL);
	PEM_write_bio_EC_PUBKEY(pub, keypair);

    BIO *bio_out = BIO_new_file("private.key", "w");
	PEM_write_bio_ECPrivateKey(bio_out, keypair, NULL, NULL, 0, NULL, NULL);
    BIO_free(bio_out);
    bio_out = BIO_new_file("public.key", "w");
	PEM_write_bio_EC_PUBKEY(bio_out, keypair);
    BIO_free(bio_out);
 
	pri_len = BIO_pending(pri);
	pub_len = BIO_pending(pub);
 
	pri_key = (char *)malloc(pri_len + 1);
	pub_key = (char *)malloc(pub_len + 1);
 
	BIO_read(pri, pri_key, pri_len);
	BIO_read(pub, pub_key, pub_len);
 
	pri_key[pri_len] = '\0';
	pub_key[pub_len] = '\0';
 
	EC_KEY_free(keypair);
	BIO_free_all(pub);
	BIO_free_all(pri);
	
	free(pri_key);
	free(pub_key);
    
    return 1;
}

void main(void)
{
    genkey();
}

署名して確認してください:


#include <stdio.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>

#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/ecdsa.h>
#include <openssl/sha.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include <openssl/sm2.h>

#include <apps/apps.h>

int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
{
    BIO *mem;
    int len, ret;
    unsigned char tbuf[1024];

    mem = BIO_new(BIO_s_mem());
    if (mem == NULL)
        return -1;
    for (;;) {
        if ((maxlen != -1) && maxlen < 1024)
            len = maxlen;
        else
            len = 1024;
        len = BIO_read(in, tbuf, len);
        if (len < 0) {
            BIO_free(mem);
            return -1;
        }
        if (len == 0)
            break;
        if (BIO_write(mem, tbuf, len) != len) {
            BIO_free(mem);
            return -1;
        }
        maxlen -= len;

        if (maxlen == 0)
            break;
    }
    ret = BIO_get_mem_data(mem, (char **)out);
    BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
    BIO_free(mem);
    return ret;
}


static int sm2utl_sign(const EVP_MD *md, BIO *in, BIO *out, const char *id,
	ENGINE *e, EC_KEY *ec_key, int sign)
{
	int ret = 0;
	EVP_MD_CTX *md_ctx = NULL;
	ECDSA_SIG *sig = NULL;
	unsigned char buf[1024];
	size_t siz = sizeof(buf);
	unsigned int ulen = sizeof(buf);
	int len;

	printf("sm2utl_sign\n");

	if (!(md_ctx = EVP_MD_CTX_new())
		|| !EVP_DigestInit_ex(md_ctx, md, e)
		|| !SM2_compute_id_digest(md, id, strlen(id), buf, &siz, ec_key)
		|| !EVP_DigestUpdate(md_ctx, buf, siz)) {
	}
	while ((len = BIO_read(in, buf, sizeof(buf))) > 0) {
		if (!EVP_DigestUpdate(md_ctx, buf, len)) {
		}
	}
	if (!EVP_DigestFinal_ex(md_ctx, buf, &ulen)) {
	}
	len = (int)ulen;

	if (sign) {
		unsigned char *p = buf;
		if (!(sig = SM2_do_sign(buf, len, ec_key))
			|| (len = i2d_ECDSA_SIG(sig, &p)) <= 0) {
		}
	}
	if (BIO_write(out, buf, len) != len) {
	}

	ret = 1;
end:
	EVP_MD_CTX_free(md_ctx);
	ECDSA_SIG_free(sig);
	return ret;
}

static int sm2utl_verify(const EVP_MD *md, BIO *in, BIO *out, BIO *sig,
	const char *id, ENGINE *e, EC_KEY *ec_key)
{
	int ret = 0;
	EVP_MD_CTX *md_ctx = NULL;
	unsigned char *sigbuf = NULL;
	unsigned char buf[1024];
	size_t siz = sizeof(buf);
	unsigned int ulen = sizeof(buf);
	int siglen, len;

	siglen = bio_to_mem(&sigbuf, 256, sig);
	if (siglen < 0) {
	}

	if (!(md_ctx = EVP_MD_CTX_new())
		|| !EVP_DigestInit_ex(md_ctx, md, e)
		|| !SM2_compute_id_digest(md, id, strlen(id), buf, &siz, ec_key)
		|| !EVP_DigestUpdate(md_ctx, buf, siz)) {
	}
	while ((len = BIO_read(in, buf, sizeof(buf))) > 0) {
		if (!EVP_DigestUpdate(md_ctx, buf, len)) {
		}
	}
	siz = sizeof(buf);
	if (!EVP_DigestFinal_ex(md_ctx, buf, &ulen)) {
	}
	/* SM2_verify() can check no suffix on signature */
	ret = SM2_verify(NID_undef, buf, ulen, sigbuf, siglen, ec_key);
	if (ret == 1) {
		printf("Signature Verification Successful\n");
	} else {
		printf("Signature Verification Failure\n");
		ret = 0;
	}

end:
	OPENSSL_free(sigbuf);
	EVP_MD_CTX_free(md_ctx);
	return ret;
}

int signature(char *msg)
{
    BIO *in = NULL, *out = NULL, *sig = NULL;
    char *keyfile = NULL;
    EVP_PKEY *pkey = NULL;
    EC_KEY *ec_key = NULL;
    int keyform = FORMAT_PEM;
    const EVP_MD *md = EVP_sm3();
    
    in  =  BIO_new_file("text.txt", "rb"); 
    out = BIO_new_file("text.sig", "wb");
    
    BIO  * key  =  NULL;
    key = BIO_new_file("private.key", "r");
    pkey=PEM_read_bio_PrivateKey(key, NULL, 0, NULL);

	if (!(ec_key = EVP_PKEY_get0_EC_KEY(pkey))
		|| !EC_KEY_is_sm2p256v1(ec_key)) {
		printf("Invalid key type\n");
		return -1;
	}
    
    sm2utl_sign(md, in, out, "1234567812345678", 0, ec_key, 1);

    return 1;
}

int verify_sig(void)
{
    const EVP_MD *md = EVP_sm3();
    BIO *in = NULL, *out = NULL, *sig = NULL;
    
    in  =  BIO_new_file("text.txt", "rb"); 
    sig = BIO_new_file("text_1.sig", "rb");

    //FILE *fp = fopen("public_cert.pem", "r");
    //X509 *cert = PEM_read_X509(fp, NULL, NULL, NULL);
    FILE *fp = fopen("public.cer", "r");
    X509 *cert = d2i_X509_fp(fp, NULL);

    EVP_PKEY *evk = X509_get_pubkey(cert);
    EC_KEY *ec_key=EVP_PKEY_get0_EC_KEY(evk);
    if (1==sm2utl_verify(md, in, out, sig, "1234567812345678", 0, ec_key))
    {
        printf("verify success\n");
    }
    else
    {
        printf("verify fail\n");
    }
    return 1;
}

void main(void)
{
    signature("1234567890123456");
    //verify_sig();
}

SM2の署名および検証プロセスでは、署名されたデータのダイジェストは直接計算されませんが、ダイジェストは特別な前処理プロセスによって取得されます。このプロセスは、要約計算の2つの段階で構成されます。

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は2バイトを占める署名者IDのビット長です。IDは署名者IDであり、国家機密規格で定義されているデフォルトの署名者IDは、UFT_8文字列で「1234567812345678」として表され、16進数で表されます。 0x31323334353637383132333435363738。したがって、デフォルトでは、ENTL値は0x0080です。a、b、x_G、y_Gは、SM2アルゴリズム標準で指定されているすべての値です。aとbは楕円曲線y = x + ax + bの係数であり、x_G、y_GはSM2アルゴリズムによって選択された基点の座標です。上記のパラメーターはすべて固定値です。a= 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC

b = 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93

x_G = 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7

y_G = 0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0

x_A || y_Aは、公開鍵の2つの部分を連結したものです。0x04の部分はないことに注意してください。上記の要素の連結された値に対してSM3操作を実行して、結果Zを取得します。2)H = SM3(Z || M)

Zは計算の最初のステップで取得されたダイジェスト、Mは署名の元のテキストです。2つを結合してから、SM3ダイジェスト計算を実行します。得られたダイジェストは前処理の結果であり、後続の署名および検証操作で使用されます。

参照:

https://www.pianshen.com/article/2043152732/
https://github.com/guanzhi/GmSSL/

https://baijiahao.baidu.com/s?id=1674018830496556781&wfr=spider&for=pc

おすすめ

転載: blog.csdn.net/eidolon_foot/article/details/111036065