您的位置:首页 > 运维架构

openssl从内存中读取RSA公钥

2014-04-12 15:10 260 查看
背景:近期需要在项目中进行RSA签名验证,厂商会给出pem格式的RSA公钥。在以往项目中使用openssl读取RSA公钥时基本都是从pem文件中读取,基本没什么问题,可最近由于项目需要需要从数据库中读取RSA公钥,经查资料发现openssl提供了bio接口以支持各种形式的秘钥读取。

在使用bio接口从内存中读取pem格式的公钥时,总是读取公钥失败,经不断查找资料,发现在我们得到base64编码的RSA公钥后,从内存中读取这个公钥时要注意以下几点:

(1)公钥字符串开头要加上“-----BEGIN PUBLIC KEY-----\n”,结尾加上“\n-----END PUBLIC KEY-----\n”。否则会出现error:0906D06C:PEM routines:PEM_read_bio:no
start line

(2)公钥字符串每隔64个字符要加一个换行,否则会报秘钥格式错误。

c++代码实现举例:

int nPublicKeyLen = strPublicKey.size(); //strPublicKey为base64编码的公钥字符串

for(int i = 64; i < nPublicKeyLen; i+=64)

{

if(strPublicKey[i] != '\n')

{

strPublicKey.insert(i, "\n");

}

i++;

}

strPublicKey.insert(0, "-----BEGIN PUBLIC KEY-----\n");

strPublicKey.append("\n-----END PUBLIC KEY-----\n");

BIO *bio = NULL;

RSA *rsa = NULL;

char *chPublicKey = const_cast<char *>(strPublicKey.c_str());

if ((bio = BIO_new_mem_buf(chPublicKey, -1)) == NULL) //从字符串读取RSA公钥

{

cout<<"BIO_new_mem_buf failed!"<<endl;

}

rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); //从bio结构中得到rsa结构

if (!rsa)

{

ERR_load_crypto_strings();

char errBuf[512];

ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));

cout<< "load public key failed["<<errBuf<<"]"<<endl;

BIO_free_all(bio);

}

由于使用RSA_vefify函数未能成功验证签名,改为使用evp相关函数进行签名验证。下面贴上使用公钥进行签名验证的代码:

string strBase64DecodedSig = base64_decode(strSignature); //strSignature为签名

char *chInAppDataSignature = const_cast<char *>(strBase64DecodedSig.c_str()); //签名先进行base64解码

int result = 0;

char *chInAppData = const_cast<char *>(strUnsignedData.c_str()); //strUnsignedData为原始数据,即未加密数据

EVP_PKEY *evpKey = NULL;

EVP_MD_CTX ctx;

evpKey = EVP_PKEY_new();

if(evpKey == NULL)

{

cout<<"error EVP_PEKY_new"<<endl;

RSA_free(rsa);

BIO_free_all(bio);return;

}

if((result = EVP_PKEY_set1_RSA(evpKey,rsa)) != 1)

{

cout<<"error EVP_PKEY_set1_RSA"<<endl;

RSA_free(rsa);

EVP_PKEY_free(evpKey);

BIO_free_all(bio);return;

}

EVP_MD_CTX_init(&ctx);

if(result == 1 && (result = EVP_VerifyInit_ex(&ctx, EVP_sha1(), NULL)) != 1)

{

cout<<"error EVP_VerfyInit_ex"<<endl;

}

if(result == 1 && (result = EVP_VerifyUpdate(&ctx, chInAppData,strUnsignedData.size())) != 1)

{

cout<<"error EVP_VerifyUpdate"<<endl;

}

if(result == 1 && (result = EVP_VerifyFinal(&ctx, (unsigned char *)chInAppDataSignature, strBase64DecodedSig.size(), evpKey)) != 1)

{

cout<<"error EVP_VerifyFinal"<<endl;

}

if(result == 1)

{

cout<<"Verify success"<<endl;

}

else

{

ERR_load_crypto_strings();

char errBuf[512];

ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));

cout<<"verify failed["<<errBuf<<"]"<<endl;

}

EVP_MD_CTX_cleanup(&ctx);

RSA_free(rsa);

EVP_PKEY_free(evpKey);

BIO_free_all(bio);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: