我正在使用TLS实现(使用OpenSSL 1.0.1s),该实现当前使用1024位RSA密钥进行加密和身份验证。我想出于性能原因升级到EC,但我需要保持向后兼容。
所以我决定使用OpenSSL的EVP API来获得尽可能多的通用代码。但是,当我想从RAM中读取证书(以ASN.1 DER格式存储)时,我遇到了问题,我无法找到完全复制EVP_PKEY
结构的方法(没有PKEY_dup
或PKEY_copy
或任何类型的东西。
我想避免切换外壳EVP_PKEY.type
所以下次升级会更顺畅,有什么建议吗?
答案 0 :(得分:1)
我设法通过转换为DER并返回来复制。一般的i2d / d2i函数调用特定的函数。
代码:
error_code_ENUM read_evp_pkey_from_ram (int index,
int DB_ID,
EVP_PKEY **pkey_ptr_PTR){
EVP_PKEY *pkey;
unsigned char *p;
unsigned char *DER_PTR;
int DER_size;
int pub_len, priv_len, type;
*pkey_ptr_PTR = NULL;
if ((pkey = sensitive_EVP_PKEY_data[DB_ID][index]) == NULL)
return error_code_no_key;
type = pkey->type;
/*passing NULL to char *out returns the length only*/
pub_len = i2d_PUBKEY(pkey, NULL);
priv_len = i2d_PrivateKey(pkey, NULL);
if (pub_len <= 0 || priv_len <= 0 )
return error_code_general_error;
DER_size = pub_len + priv_len + 2 * sizeof(UINT_16);
if ((DER_PTR = OPENSSL_malloc(DER_size)) == NULL)
return error_code_no_memory;
/*
* store the key in buffer as:
* |public key length | public key | private key length | private key|
*/
p = DER_PTR;
*(UINT_16*)p = pub_len;
p += 2;
pub_len = i2d_PUBKEY(pkey,&p);/*p is incremented here by the key size*/
*(UINT_16*)p = priv_len;
p += 2;
priv_len = i2d_PrivateKey(pkey,&p);
p = DER_PTR + 2;
/*pass NULL to EVP_PKEY *key causes a fresh EVP_PKEY struct to be allocated and a pointer to it returned*/
pkey = d2i_PUBKEY(NULL, (const unsigned char **)&p, pub_len);
if (pkey == NULL){
OPENSSL_free(DER_PTR);
return error_code_general_error;
}
priv_len = *(UINT_16 *)p;
if (priv_len == 0){
EVP_PKEY_free(pkey);
OPENSSL_free(DER_PTR);
return error_code_general_error;
}
p += 2;
/*now pass &pkey*/
if (d2i_PrivateKey(type, &pkey, (const unsigned char **)&p, priv_len) == NULL){
OPENSSL_free(DER_PTR);
return error_code_general_error;
}
OPENSSL_free(DER_PTR);
*pkey_ptr_PTR = pkey;
return error_code_no_error;
请注意,i2d / d2i函数会增加指定的指针
答案 1 :(得分:0)
根据您的问题,您可以尝试使用EVP_PKEY_up_ref()
(增加'filter' value = '2'
引用计数器),然后将指针传递给原始EVP_PKEY
。通过这种方式,您可以安全地使用EVP_PKEY
then(首先递减计数器,只有当它变为零时才真正释放)。