国密sm2签名验签

生成私钥:

#include <stdio.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/evp.h>
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>

#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
int make_server_private_key()
{
    OpenSSL_add_all_ciphers();
    OpenSSL_add_all_digests();
    ERR_load_crypto_strings();

    SSL_CTX *ctx = SSL_CTX_new (SSLv23_server_method ());
    SSL_CTX_set_options (ctx,
                         SSL_OP_SINGLE_DH_USE |
                         SSL_OP_SINGLE_ECDH_USE |
                         SSL_OP_NO_SSLv2);

    EVP_PKEY *evk = EVP_PKEY_new();

    EC_KEY *ec_server = EC_KEY_new_by_curve_name (NID_sm2p256v1);
    if (! ec_server)
        printf("ecdh error!EC_KEY_new_by_curve_name\n");

    EC_KEY_generate_key(ec_server);
    BIO *bio_out = BIO_new_file("server_private.key", "w");

    PEM_write_bio_ECPrivateKey(bio_out, ec_server, NULL, NULL, 0, NULL, NULL);
    BIO_free(bio_out);

    EC_KEY_free(ec_server);
    EVP_PKEY_free(evk);

    return 0;
}

生成证书

int make_cert(char* name_C, char* name_S, char* name_L, char* name_O, char * name_OU, char* name_CN, 
           char* PrivateKeyFileName, char* CertFileName )
{
    X509 *x;
    EVP_PKEY *pk;
    X509_NAME *name = NULL;
    BIO  * key  =  NULL;

    key  =  BIO_new(BIO_s_file()); 
    BIO_read_filename(key,PrivateKeyFileName);
    EC_KEY *ecdh = PEM_read_bio_ECPrivateKey(key, NULL, NULL, NULL);
    EVP_PKEY *evk = EVP_PKEY_new();
    EVP_PKEY_set1_EC_KEY(evk, ecdh);

    X509 *x509 = NULL;

    if (evk == NULL)
    {
        abort();
        return(0);
    }
    else
        pk = evk;

    if ((x = X509_new()) == NULL)
        return(0);

    X509_set_version(x, 2);
    int serial = 12345;
    ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
    X509_gmtime_adj(X509_get_notBefore(x), 0);
    int days = 36500;
    X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days);
    X509_set_pubkey(x, pk);

    name = X509_get_subject_name(x);

    X509_NAME_add_entry_by_txt(name, "C",
                               MBSTRING_ASC, name_C, -1, -1, 0);

    X509_NAME_add_entry_by_txt(name, "S",
                               MBSTRING_ASC, name_S, -1, -1, 0);

    X509_NAME_add_entry_by_txt(name, "L",
                               MBSTRING_ASC, name_L, -1, -1, 0);

    X509_NAME_add_entry_by_txt(name, "O",
                               MBSTRING_ASC, name_O, -1, -1, 0);

    X509_NAME_add_entry_by_txt(name, "OU",
                               MBSTRING_ASC, name_OU, -1, -1, 0);

    X509_NAME_add_entry_by_txt(name, "CN",
                               MBSTRING_ASC, name_CN, -1, -1, 0);


    X509_NAME *issuer_name=NULL;

    if (!issuer_name)
        X509_set_issuer_name(x, name);
    else
        X509_set_issuer_name(x, issuer_name);

    int n=X509_sign(x, evk, EVP_sm3());

    x509 = x;
    evk = pk;

    BIO *bio_x = BIO_new_file(CertFileName, "w");
    PEM_write_bio_X509(bio_x, x509);

    printf("n=%d\n",n);

    BIO_free(bio_x);
    EVP_PKEY_free(evk);
    EC_KEY_free(ecdh);
    X509_free(x509);

    return(1);
}

以下代码有可能不符合国标

签名

int signature(char *msg)
{
    int ret = 0;
    unsigned int slen=256;
    unsigned char sig[256];
    

    BIO  * key  =  NULL;

    key  =  BIO_new(BIO_s_file()); 
    BIO_read_filename(key,"server_private.key");
    EC_KEY *ecdh = PEM_read_bio_ECPrivateKey(key, NULL, NULL, NULL);
    printf("sig len:%d\n", ECDSA_size(ecdh));
    if (!SM2_sign(0,msg, strlen(msg), sig,&slen,ecdh))
    {
       return 0;
    }
    
    FILE *fp = fopen("server_16.sig", "wb");
    for(int i=0; i < slen; i++)
    {
        fwrite(((unsigned char*)(sig+i)), 1, 1, fp);
    }    
    fclose(fp);

    printf("slen:%d\n", slen);
    for(int i=0; i < slen; i++)
    {
    	printf("%02x ", *((unsigned char*)(sig+i)));
    }
    printf("\n");

    /* 成功 */
    ret = 1;

    /* 清理 */


    return ret;
}

验签

int verify_sig(void *sig, char *msg, size_t slen)
{
    int nRet;
    ECDSA_SIG *s;
    const unsigned char *p = sig;
    unsigned char *der = NULL;
    int derlen = -1;
    int ret = -1;
    
    FILE *fp = fopen("server_cert.pem", "r");
    X509 *cert = PEM_read_X509(fp, NULL, NULL, NULL);
    //FILE *fp = fopen("server_cert.der", "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);

    printf("\nslen:%ld\n", slen);
    for(int i=0; i < slen; i++)
    {
    	printf("%02x ", *((unsigned char*)(sig+i)));
    }
    printf("\n");

    nRet = SM2_verify(0,msg, strlen(msg), sig, slen,ec_key);
    return nRet == 1 ? 1 : 0;
}

猜你喜欢

转载自blog.csdn.net/eidolon_foot/article/details/110824516