Skip to content

如何通过原生字符串秘钥生成EVP_PKEY结构? #3

@ccjinghang

Description

@ccjinghang

@tan00 您好!
请教个问题,如何通过原生字符串秘钥生成EVP_PKEY结构?
我的方式如下:
EVP_PKEY* covert_string_evp_pkey_new(unsigned char* buf,int is_public)
{
if (NULL == buf)
{
return NULL;
}

EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_sm2p256v1);
long keylen=0;
unsigned char *key = NULL;
if (!(key = OPENSSL_hexstr2buf((char *)buf, &keylen)))
{
	return NULL;
}

/*
if (keylen != 32 )
{
	printf("__LINE__=%ld\n",__LINE__);
               // OPENSSL_cleanse(key, keylen);
}*/
if(is_public)
{
	if(!EC_KEY_oct2key(eckey,key, keylen,NULL))
	{
		OPENSSL_cleanse(key, keylen);
	}
}
else
{
	if (!EC_KEY_oct2priv(eckey, key, keylen))
	{
		OPENSSL_cleanse(key, keylen);
	}
}
OPENSSL_cleanse(key, keylen);
EVP_PKEY *evp_key = EVP_PKEY_new();
if(!EVP_PKEY_set1_EC_KEY(evp_key,eckey))
{
	OPENSSL_cleanse(key, keylen);
	return NULL;
}

return evp_key;

}
采用这种方式确实可以生成EVP_PKEY,且我内部加验签也可以成功,加验签如下:
struct AlgorithmParams
{
const unsigned char *public_key;
const unsigned char *private_key;
int pri_key_len;
int pub_key_len;
const unsigned char *str_in;
int str_in_len;
unsigned char *str_out;
int str_out_len;
const unsigned char *iv;
int pendding; //0 不填充 默认填充
};
int sm2_sign(struct AlgorithmParams *param)
{
if(NULL == param)
{
fprintf(stderr, "%s() failed to sm2_sign\n", func);
return -1;
}
char szErr[1024];
int nRet = 0;
int value = 0;
EVP_PKEY *pkey = NULL;
const EVP_MD *md = NULL;
EVP_MD_CTX *mdctx = NULL;
if(!(pkey = covert_string_evp_pkey_new(param->private_key,0)))
{
printf("LINE=%d\n",LINE);
return -1;
}

md = EVP_sm3();
if(!(mdctx=EVP_MD_CTX_new()))
{
	fprintf(stderr, "%s() failed to call EVP_MD_CTX_new\n", __func__);
	nRet = -1;
	goto sign_ret;
}

if(!EVP_DigestSignInit(mdctx, NULL,md, NULL,pkey))
{
	value  = ERR_get_error();
	ERR_error_string( value, szErr );
	fprintf( stderr,"OpenSSL_Sign: EVP_SignUpdate failed: \nopenssl return %d, %s\n", value, szErr );
	nRet = -1;
	goto sign_ret;
}

if(!EVP_DigestSignUpdate(mdctx, param->str_in, param->str_in_len))
{
	value  = ERR_get_error();
	ERR_error_string( value, szErr );
	fprintf( stderr,"OpenSSL_Sign: EVP_SignUpdate failed: \nopenssl return %d, %s\n", value, szErr );
	nRet = -2;
	goto sign_ret;
}

if(!EVP_DigestSignFinal(mdctx, param->str_out, &(param->str_out_len)))
{
	value  = ERR_get_error();
	ERR_error_string( value, szErr );
	fprintf( stderr,"OpenSSL_Sign: EVP_SignFinal failed: \nopenssl return %d, %s\n", value, szErr );
	nRet = -3;
	goto sign_ret;
}

sign_ret:
/if( !EVP_MD_CTX_cleanup(mdctx) ) {
value = ERR_get_error();
ERR_error_string( value, szErr );
fprintf( stderr,"OpenSSL_Sign: EVP_ctx_cleanup failed: \nopenssl return %d, %s\n", value, szErr );
}
/
EVP_PKEY_free(pkey);
EVP_MD_CTX_destroy(mdctx);
return nRet;
}

int sm2_verify(struct AlgorithmParams *param)
{
if(NULL == param)
{
fprintf(stderr, "%s() failed to sm2_verify\n", func);
return -1;
}
char szErr[1024];
int nRet = 0;
int value = 0;
EVP_PKEY *pkey = NULL;
const EVP_MD *md = NULL;
EVP_MD_CTX *mdctx = NULL;
if(! (pkey = covert_string_evp_pkey_new(param->public_key,1)))
{
return -1;
}

md = EVP_sm3();

if(!(mdctx=EVP_MD_CTX_new()))
{
	fprintf(stderr, "%s() failed to call EVP_MD_CTX_new\n", __func__);
	nRet = -1;
	goto verify_ret;
}
if(!EVP_DigestVerifyInit(mdctx, NULL,md, NULL,pkey))
{
	value  = ERR_get_error();
	ERR_error_string( value, szErr );
	fprintf( stderr,"OpenSSL_Sign: EVP_DigestVerifyInit failed: \nopenssl return %d, %s\n", value, szErr );
	nRet = -1;
	goto verify_ret;
}

if(!EVP_DigestVerifyUpdate(mdctx, param->str_in, param->str_in_len))
{
	value  = ERR_get_error();
	ERR_error_string( value, szErr );
	fprintf( stderr,"OpenSSL_Sign: EVP_DigestVerifyUpdate failed: \nopenssl return %d, %s\n", value, szErr );
	nRet = -2;
	goto verify_ret;
}
if(!EVP_DigestVerifyFinal(mdctx, param->str_out, param->str_out_len))
{
	value  = ERR_get_error();
	ERR_error_string( value, szErr );
	fprintf( stderr,"OpenSSL_Sign: EVP_DigestVerifyFinal failed: \nopenssl return %d, %s\n", value, szErr );
	nRet = -3;
	goto verify_ret;
}

verify_ret:
/if( !EVP_MD_CTX_cleanup(mdctx) ) {
value = ERR_get_error();
ERR_error_string( value, szErr );
fprintf( stderr,"OpenSSL_Sign: EVP_ctx_cleanup failed: \nopenssl return %d, %s\n", value, szErr );
}
/
EVP_PKEY_free(pkey);
EVP_MD_CTX_destroy(mdctx);
return nRet;
}
确实可以加验签成功,但是,采用java bc加签的签名,我这边无法验签成功,反之亦然。是sm2的参数设置有误还是?请指教!
验证java bc的签名报错结果如下:
openssl return 269181073, error:100B6091:elliptic curve routines:ec_GFp_simple_oct2point:invalid encoding

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions