gmssl national secret sm2 (générer une vérification de certificat de signature de paire de clés privées)

Générez une paire de clés:

#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();
}

Signez et vérifiez:


#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();
}

Dans le processus de signature et de vérification SM2, le condensé des données signées n'est pas directement calculé, mais le condensé est obtenu via un processus de prétraitement spécial. Ce processus comprend deux étapes de calcul récapitulatif:

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 représente l'épissage (cascade) des données d'élément de signature.

Parmi eux, ENTL est la longueur en bits de l'ID du signataire, qui occupe deux octets; ID est l'ID du signataire, l'ID du signataire par défaut défini dans la norme nationale secrète est représenté par la chaîne UFT_8 comme "1234567812345678", exprimé en hexadécimal. 0x31323334353637383132333435363738. Ainsi, par défaut, la valeur ENTL est 0x0080.a, b, x_G, y_G sont toutes les valeurs données dans le standard d'algorithme SM2. a et b sont les coefficients de la courbe elliptique y = x + ax + b, et x_G, y_G sont les coordonnées du point de base sélectionné par l'algorithme SM2. Les paramètres ci-dessus sont tous des valeurs fixes: a = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC

b = 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93

x_G = 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7

y_G = 0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0

x_A || y_A est la concaténation des deux parties de la clé publique. Notez qu'il n'y a pas de partie de 0x04; effectuez l'opération SM3 sur les valeurs concaténées des éléments ci-dessus pour obtenir le résultat Z. 2) H = SM3 (Z || M)

Z est le condensé obtenu à la première étape du calcul et M est le texte original de la signature. Joignez les deux ensemble, puis effectuez le calcul du condensé SM3. Le résumé obtenu est le résultat d'un prétraitement, qui sera utilisé dans les opérations de signature et de vérification ultérieures.

référence:

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

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

Je suppose que tu aimes

Origine blog.csdn.net/eidolon_foot/article/details/111036065
conseillé
Classement