国密算法

//

//
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/gmapi.h>


#include "utils.h"


int compress_public_key(const unsigned char* puk, int puk_len, char* compressed_puk, int* compressed_puk_len)
{
    EC_GROUP *curve_group = NULL;
    EC_POINT *point=NULL;
    BIGNUM *xy = NULL;
    BIGNUM *x;
    BIGNUM *y;
    unsigned char buff[128] = { 0x0 };
    int result = 0;


    curve_group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);


    if(curve_group == NULL)
    {
        result = -2;
        return  result;
    }
    xy = BN_new();
    x = BN_new();
    y = BN_new();


    // create a big number from the unsigned char array
    BN_bin2bn(puk, puk_len, xy);
    BN_bin2bn(puk, 32, x);
    BN_bin2bn(puk+32, 32, y);


    point = EC_POINT_new(curve_group);
    if(point==NULL)
    {
        result = -3;
        return  result;
    }


    if (!EC_POINT_set_affine_coordinates_GFp(curve_group, point, x, y, NULL)) {
        return -5;
    }


    if (!EC_POINT_is_on_curve(curve_group, point, NULL)) {
        return -4;
    }


    if ((result = EC_POINT_point2oct(curve_group, point,
                                     POINT_CONVERSION_COMPRESSED,
                                     buff, sizeof(buff), NULL)) != 33) {
        return -6;
    }


    memcpy(compressed_puk, buff, result);


    *compressed_puk_len = result;


    return 0;
}


int uncompress_public_key(unsigned char *in, int in_len, unsigned char *out, int *out_len)
{
    EC_GROUP *curve_group = NULL;//
    EC_POINT *point=NULL;
    BIGNUM *x_compressed = NULL;
    int y_chooser_bit = 0;
    int results = 0;
    size_t returnsize = 0;


    unsigned char xy[200]={0};
    unsigned char x_compressed_byte_array[33]={0};


    do{
        if(in[0] == 0x03)
        {
            y_chooser_bit = 1;
        }else{
            y_chooser_bit = 0;
        }


        memcpy(x_compressed_byte_array, in, 33);
        x_compressed=BN_new();


        if(x_compressed==NULL)
        {
            results = -1;
            break;
        }
        curve_group=EC_GROUP_new_by_curve_name(NID_sm2p256v1);
        if(curve_group==NULL)
        {
            results = -2;
            break;
        }


        // create a big number from the unsigned char array
        BN_bin2bn(&x_compressed_byte_array[1],sizeof(x_compressed_byte_array)-1,x_compressed);
        point = EC_POINT_new(curve_group);
        if(point==NULL)
        {
            results = -3;
            break;
        }
        //说明:素数域椭圆曲线,给定压缩坐标x和y_bit参数,设置point的几何坐标;用于将Octet-String转化为椭圆曲线上的点;
        EC_POINT_set_compressed_coordinates_GFp(curve_group, point,
                                                x_compressed,
                                                y_chooser_bit, NULL);


        //printf("results=%d\r\n",results);
        if (!EC_POINT_is_on_curve(curve_group,point,NULL))
        {
            results = -4;
            break;
        }


        returnsize = EC_POINT_point2oct(curve_group, point,
                                        POINT_CONVERSION_UNCOMPRESSED,
                                        &xy[0], sizeof(xy), NULL); // 49


        if(returnsize!=65)
        {
            results = -5;
            break;
        }
        //printf("returnsize=%d\r\n",returnsize);
    }while(0);


    // clean up allocated memory
    if(x_compressed)
        BN_free(x_compressed);
    if(point)
        EC_POINT_free(point);
    if(curve_group)
        EC_GROUP_free(curve_group);


    if(0==results)
    {
        memcpy(out, xy, 65);
        *out_len = 65;
    }
    return results;
}


int hexToBin(const char* src, int src_len, char* dst, int* dst_len)
{
    char tmpbuff[4] = { 0x0};
    int i = 0;
    int t;


    if (src_len < 2 && (src_len % 2) != 0) {
        return -1;
    }


    *dst_len = src_len / 2;


    for(i=0; i< *dst_len; i++) {
        memcpy(tmpbuff, src + i*2, 2);
        t = strtol(tmpbuff, NULL, 16);
        *(dst + i) = t & 0xff;
        memset(tmpbuff, 0x0, sizeof(tmpbuff));
    }


    return 0;
}


int binToHex(const char* src, int src_len, char* dst, int* dst_len)
{
    int i = 0;


    for(i= 0; i < src_len; i++) {
        sprintf(dst + i*2, "%02X", *(src + i) & 0xff);
    }


    *dst_len = src_len *2;


    return 0;
}


int sm2_sign(const unsigned char* pvk, int pvk_len, const char* data, int data_len, char* signature, int* signature_len)
{
    EVP_PKEY *pkey = NULL;
    EC_KEY *ec_key = NULL;


    const EVP_MD *id_md = EVP_sm3();
    const EVP_MD *msg_md = EVP_sm3();


    int type = NID_sm2p256v1;
    unsigned char dgst[EVP_MAX_MD_SIZE];
    size_t dgstlen = 32;
    char *id = "1234567812345678";


    ECDSA_SIG *sm2sig = NULL;
    unsigned char sig[256] = { 0x0 };
    unsigned int siglen = 0;


    const BIGNUM *sig_r;
    const BIGNUM *sig_s;
    const unsigned char * p;
    int i;
    unsigned char* tp;


    pkey = d2i_AutoPrivateKey(NULL, &pvk, pvk_len);


    ec_key = EVP_PKEY_get0_EC_KEY(pkey);


    SM2_compute_message_digest(id_md, msg_md,
                               (const unsigned char *)data, data_len, id, strlen(id),
                               dgst, &dgstlen, ec_key);
#ifdef DEBUG
    printf("dgst1 = ");
    for(i = 0; i< dgstlen; i++) {
        printf("%02X", dgst[i]);
    }
    printf("\n");
#endif


    siglen = sizeof(sig);
    if (!SM2_sign(type, dgst, dgstlen, sig, &siglen, ec_key)) {
        fprintf(stderr, "error: %s %d\n", __FUNCTION__, __LINE__);
        return -1;
    }


    p = sig;
    sm2sig  = d2i_ECDSA_SIG(NULL, &p, siglen);


    ECDSA_SIG_get0(sm2sig, &sig_r, &sig_s);


    siglen = BN_bn2bin(sig_r, signature);
    *signature_len = siglen;


    siglen = BN_bn2bin(sig_s, signature + siglen);


    *signature_len += siglen;


    return 0;
}


int sm2_sign_verify(const unsigned char* puk, int puk_len, const unsigned char* data, int data_len, const unsigned char* signature, int sig_len)
{
    EC_KEY *ec_key = NULL;
    BIGNUM *x = NULL;
    BIGNUM *y = NULL;
    EC_GROUP* group;
    int ret = -1;
    const EVP_MD *id_md = EVP_sm3();
    const EVP_MD *msg_md = EVP_sm3();


    int type = NID_sm2p256v1;
    unsigned char dgst[EVP_MAX_MD_SIZE];
    size_t dgstlen = 32;
    char *id = "1234567812345678";
    int i = 0;
    ECDSA_SIG *sig = NULL;
    BIGNUM *r = NULL;
    BIGNUM *s = NULL;
    unsigned char *pp = NULL;
    unsigned char *pp_sig = NULL;
    int pp_len = 0;
    unsigned char* tp = NULL;


#ifdef DEBUG
    printf("puk[%d] = ", puk_len);
    for(i = 0; i< puk_len; i++) {
        printf("%02X", puk[i]&0xff);
    }
    printf("\n");


    printf("data[%d] = ", data_len);
    for(i = 0; i< data_len; i++) {
        printf("%02X", data[i]&0xff);
    }
    printf("\n");


    printf("sign[%d] = ", sig_len);
    for(i = 0; i< sig_len; i++) {
        printf("%02X", signature[i]&0xff);
    }
    printf("\n");
#endif


    group = EC_GROUP_new_by_curve_name(NID_sm2p256v1);


    if (!(ec_key = EC_KEY_new())) {
        ret = -2;
        goto end;
    }


    if (!EC_KEY_set_group(ec_key, group)) {
        ret = -3;
        goto end;
    }


    if ((x = BN_bin2bn(puk, 32, NULL)) == NULL) {
        ret = -4;
        goto end;
    }
    if ((y = BN_bin2bn(puk+32, 32, NULL)) == NULL) {
        ret = -5;
        goto end;
    }


    if (!EC_KEY_set_public_key_affine_coordinates(ec_key, x, y)) {
        ret = -6;
        goto end;
    }


    ret = SM2_compute_message_digest(id_md, msg_md,
                               data, data_len, id, strlen(id),
                               dgst, &dgstlen, ec_key);
#ifdef DEBUG
    printf("ret = [%d] = ", ret);
    ret = EVP_MD_size(msg_md);
    printf("EVP_MD_size = [%d] = ", ret);


    printf("dgst[%d] = ", dgstlen);
    for(i = 0; i< dgstlen; i++) {
        printf("%02X", dgst[i]&0xff);
    }
    printf("\n");


    printf("id_md [%d] = ", 64);
    for(i = 0; i< 64; i++) {
        printf("%02X", ((unsigned char*)id_md)[i]&0xff);
    }
    printf("\n");


    printf("msg_md[%d] = ", 64);
    for(i = 0; i< 64; i++) {
        printf("%02X", ((unsigned char*)msg_md)[i]&0xff);
    }
    printf("\n");


    printf("ec_key[%d] = ", 64);
    for(i = 0; i< 64; i++) {
        printf("%02X", ((unsigned char*)ec_key)[i]&0xff);
    }
    printf("\n");
#endif


    if ((r = BN_bin2bn(signature, 32, NULL)) == NULL) {
        ret = -4;
        goto end;
    }


    if ((s = BN_bin2bn(signature+32, 32, NULL)) == NULL) {
        ret = -5;
        goto end;
    }


    pp_len = ECDSA_size(ec_key);
    if ((pp_sig = OPENSSL_malloc(pp_len)) == NULL) {
        fprintf(stderr, "error : %s %d\n", __FUNCTION__, __LINE__);
        goto end;
    }


    sig = ECDSA_SIG_new();


    if (!ECDSA_SIG_set0(sig, r, s)) {
        fprintf(stderr, "error : %s %d\n", __FUNCTION__, __LINE__);
        goto end;
    }


    pp = pp_sig;


    pp_len = i2d_ECDSA_SIG(sig, &pp);
#ifdef DEBUG
    printf("sig = ");
    for(i = 0; i< pp_len; i++) {
        printf("%02X", pp_sig[i]);
    }
    printf("\n");
#endif
    ret = SM2_verify(type, dgst, dgstlen, pp_sig, pp_len, ec_key);


    if (1 != ret) {
        fprintf(stderr, "error %d : %s %d\n", ret, __FUNCTION__, __LINE__);
        ret = -7;
        goto end;
    }


    ret = 0;


end:


    return ret;
}


void dump_cert_request(CERT_REQUEST_T *cert_req)
{
    int i = 0;
    unsigned char* p;
    printf("Cert request file, length = %d bytes\n", sizeof(CERT_REQUEST_T));
    p = (unsigned char*)cert_req;


    for(i = 0; i< sizeof(CERT_REQUEST_T); i++) {
        printf("%02X", *(p+i));
    }
    printf("\n");


    printf("Record header: %02X\n", cert_req->header);
    printf("Service id: ");


    for(i = 0; i< sizeof(cert_req->service_id); i++) {
        printf("%02X", cert_req->service_id[i]);
    }
    printf("\n");


    printf("Cert format: %02X\n", cert_req->format);
    printf("Expire date: ");


    for(i = 0; i< sizeof(cert_req->expire_date); i++) {
        printf("%02X", cert_req->expire_date[i]);
    }
    printf("\n");


    printf("Record number: ");
    for(i = 0; i< sizeof(cert_req->record_number); i++) {
        printf("%02X", cert_req->record_number[i]);
    }
    printf("\n");


    printf("Sign algo: %02X\n", cert_req->sign_id);
    printf("Encrypt algo: %02X\n", cert_req->encrypt_id);


    printf("SM2 public key param: %02X\n", cert_req->puk_param_id);
    printf("SM2 public key length: %02X\n", cert_req->puk_len);


    printf("SM2 public key: ");
    for(i = 0; i< sizeof(cert_req->puk); i++) {
        printf("%02X", cert_req->puk[i]);
    }
    printf("\n");


    printf("SM2 signature: ");
    for(i = 0; i< sizeof(cert_req->signature); i++) {
        printf("%02X", cert_req->signature[i]);
    }
    printf("\n");


    return;
}


void dump_cert_response(CERT_RESPONSE_T* cert_resp)
{


    int i = 0;
    unsigned char* p;
    printf("Cert response file, length = %d bytes\n", sizeof(CERT_RESPONSE_T));
    p = (unsigned char*)cert_resp;


    for(i = 0; i< sizeof(CERT_RESPONSE_T); i++) {
        printf("%02X", *(p+i));
    }
    printf("\n");


    printf("Record header: %02X\n", cert_resp->header);
    printf("Service id: ");


    for(i = 0; i< sizeof(cert_resp->service_id); i++) {
        printf("%02X", cert_resp->service_id[i]);
    }
    printf("\n");


    printf("Root CA public key index: %02X\n", cert_resp->ca_puk_idx);


    printf("Cert format: %02X\n", cert_resp->format);


    printf("Issuer id: ");
    for(i = 0; i< sizeof(cert_resp->issuer_id); i++) {
        printf("%02X", cert_resp->issuer_id[i]);
    }
    printf("\n");


    printf("Expire date: ");
    for(i = 0; i< sizeof(cert_resp->expire_date); i++) {
        printf("%02X", cert_resp->expire_date[i]);
    }
    printf("\n");


    printf("Serial number: ");
    for(i = 0; i< sizeof(cert_resp->record_number); i++) {
        printf("%02X", cert_resp->record_number[i]);
    }
    printf("\n");


    printf("Sign algo: %02X\n", cert_resp->sign_id);
    printf("Encrypt algo: %02X\n", cert_resp->encrypt_id);


    printf("SM2 public key param: %02X\n", cert_resp->puk_param_id);
    printf("SM2 public key length: %02X\n", cert_resp->puk_len);


    printf("SM2 public key: ");
    for(i = 0; i< sizeof(cert_resp->puk); i++) {
        printf("%02X", cert_resp->puk[i]);
    }
    printf("\n");


    printf("SM2 signature: ");
    for(i = 0; i< sizeof(cert_resp->signature); i++) {
        printf("%02X", cert_resp->signature[i]);
    }
    printf("\n");


    return;


}


int dump_cert_response_to_file(int fd, CERT_RESPONSE_T* cert_resp)
{
    unsigned char *p;
    int len;
    int ret;


    p = (unsigned char*)cert_resp;
    len = sizeof(CERT_RESPONSE_T);


    ret = write(fd, p, len);


    if (len != ret) {
        printf("Failed to write file.\n");
        return -1;
    }


    return 0;
}




int read_private_key_from_pem(const char* pemfile, unsigned char* private_key, int* private_key_len)
{
    BIO *fp;
    char *name = 0;
    char *header = 0;
    unsigned char *buff = 0x0 ;
    long buff_len;
    int ret = -1;


    if (access(pemfile, R_OK) != 0 ) {
        printf("Not found file: %s\n", pemfile);
        return -1;
    }


    fp = BIO_new_file(pemfile, "r");
    if (fp == NULL) {
        printf("Failed to open file: %s", pemfile);
        ret = -2;
        goto  err;
    }


    ret = PEM_read_bio(fp, &name, &header, &buff, &buff_len);
#ifdef DEBUG
    printf("1buff ret = %d len = %d name = %s data = \n", ret, buff_len, name);
    for(int i = 0; i<buff_len; i++) {
        printf("%02X", buff[i]);
    }
    printf("\n");
#endif


    if (strncmp(name, "EC PARAMETERS", 13) == 0 ) {
        PEM_read_bio(fp, &name, &header, &buff, &buff_len);
#ifdef DEBUG
        printf("2buff len = %d data = \n", buff_len);
        for(int i = 0; i<buff_len; i++) {
            printf("%02X", buff[i]);
        }
        printf("\n");
#endif
        memcpy(private_key, buff, buff_len);
        *private_key_len = buff_len;
        ret = 0;
    } else {
        printf("WARNING: This is not a EC key file.\n");
        ret = -3;
        goto  err;
    }
    err:
    BIO_free(fp);
    return ret;
}


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值