//
//
#include
#include
#include
#include
#include
#include
#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 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 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;
}