如何使用 OpenSSL API 从其 PEM 格式字符串中读取 RSA public 密钥?
How to read an RSA public key from a its PEM format string using the OpenSSL API?
我可以使用 PEM_read_RSA_PUBKEY
函数轻松读取 PEM 文件。但是,我在可执行文件中内置了一个 public 键,我不想创建临时文件。阅读此 example/tutorial:http://hayageek.com/rsa-encryption-decryption-openssl-c/ 我想出了以下解决方案:
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <QFile>
#include <QByteArray>
#include <stdexcept>
#include <cassert>
#include <cstring>
RSA* createRSA(const char* key)
{
RSA *rsa = nullptr;
BIO *keybio ;
keybio = BIO_new_mem_buf(key, -1); // !!!
if (!keybio)
{
throw std::runtime_error("Failed to create key BIO");
}
rsa = PEM_read_bio_RSA_PUBKEY(keybio, nullptr, nullptr, nullptr); // !!!
if(!rsa )
{
throw std::runtime_error("Failed to create RSA");
}
BIO_free(keybio); // !!!
return rsa;
}
int main()
{
QFile publicKeyFile(":/public.pem");
publicKeyFile.open(QIODevice::ReadOnly);
auto data = publicKeyFile.readAll();
RSA* rsa = createRSA(data.data());
EVP_PKEY* verificationKey = EVP_PKEY_new();
auto rc = EVP_PKEY_assign_RSA(verificationKey, RSAPublicKey_dup(rsa));
assert(rc == 1);
if(verificationKey)
EVP_PKEY_free(verificationKey);
return 0;
}
然而我有很多疑惑:
BIO_new_mem_buf
需要一个const void*
参数,我可以只传一个const char*
吗?我什至从 docs. 都没有弄清楚
- 在调用
PEM_read_bio_RSA_PUBKEY
函数时,原来的例子是这样调用的:
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
即使在阅读 docs 之后我也不明白。我认为我应该将 nullptr
作为第二个参数传递。
- 我应该在返回的
RSA
指针上调用 RSA_free
吗? valgrind
无论我是否这样做,都没有发现内存泄漏。
- 我应该在完成
BIO
后调用 BIO_free(keybio);
吗? valgrind
如果我不这样做,就会发现内存泄漏,并且在教程中缺少此调用。如果我调用 BIO_free(keybio);
,则意味着 PEM_read_bio_RSA_PUBKEY
从 BIO
复制了数据,而不仅仅是链接到它。但如果是这样的话,我不应该释放 RSA
吗?
非常感谢任何建议。我不知道什么是真实的了。
每个问题的答案:
- 是的,你可以传一个
const char*
,就是投。
PEM_read_bio_RSA_PUBKEY
为您创建分配RSA结构。参数(如果不为空)用于存储指向它的指针,这将与 return 值相同。用于简化编码:if (!PEM_read_bio_RSA_PUBKEY(keybio, &rsa, nullptr, nullptr)) { /* error */ }
是的,你必须使用RSA_free
来释放它。
- 是的,你也得发布。
P.S.: OpenSSL 文档有点棘手,因为有许多类似的功能,只是算法、结构或数据格式不同。在 man page 的末尾有一个 Description 部分,其中对它们进行了解释,删除了每个变体的细节。但是,是的,如果没有好的教程或示例,很难找到它。
我可以使用 PEM_read_RSA_PUBKEY
函数轻松读取 PEM 文件。但是,我在可执行文件中内置了一个 public 键,我不想创建临时文件。阅读此 example/tutorial:http://hayageek.com/rsa-encryption-decryption-openssl-c/ 我想出了以下解决方案:
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <QFile>
#include <QByteArray>
#include <stdexcept>
#include <cassert>
#include <cstring>
RSA* createRSA(const char* key)
{
RSA *rsa = nullptr;
BIO *keybio ;
keybio = BIO_new_mem_buf(key, -1); // !!!
if (!keybio)
{
throw std::runtime_error("Failed to create key BIO");
}
rsa = PEM_read_bio_RSA_PUBKEY(keybio, nullptr, nullptr, nullptr); // !!!
if(!rsa )
{
throw std::runtime_error("Failed to create RSA");
}
BIO_free(keybio); // !!!
return rsa;
}
int main()
{
QFile publicKeyFile(":/public.pem");
publicKeyFile.open(QIODevice::ReadOnly);
auto data = publicKeyFile.readAll();
RSA* rsa = createRSA(data.data());
EVP_PKEY* verificationKey = EVP_PKEY_new();
auto rc = EVP_PKEY_assign_RSA(verificationKey, RSAPublicKey_dup(rsa));
assert(rc == 1);
if(verificationKey)
EVP_PKEY_free(verificationKey);
return 0;
}
然而我有很多疑惑:
BIO_new_mem_buf
需要一个const void*
参数,我可以只传一个const char*
吗?我什至从 docs. 都没有弄清楚
- 在调用
PEM_read_bio_RSA_PUBKEY
函数时,原来的例子是这样调用的:rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
即使在阅读 docs 之后我也不明白。我认为我应该将nullptr
作为第二个参数传递。 - 我应该在返回的
RSA
指针上调用RSA_free
吗?valgrind
无论我是否这样做,都没有发现内存泄漏。 - 我应该在完成
BIO
后调用BIO_free(keybio);
吗?valgrind
如果我不这样做,就会发现内存泄漏,并且在教程中缺少此调用。如果我调用BIO_free(keybio);
,则意味着PEM_read_bio_RSA_PUBKEY
从BIO
复制了数据,而不仅仅是链接到它。但如果是这样的话,我不应该释放RSA
吗?
非常感谢任何建议。我不知道什么是真实的了。
每个问题的答案:
- 是的,你可以传一个
const char*
,就是投。 PEM_read_bio_RSA_PUBKEY
为您创建分配RSA结构。参数(如果不为空)用于存储指向它的指针,这将与 return 值相同。用于简化编码:if (!PEM_read_bio_RSA_PUBKEY(keybio, &rsa, nullptr, nullptr)) { /* error */ }
是的,你必须使用
RSA_free
来释放它。- 是的,你也得发布。
P.S.: OpenSSL 文档有点棘手,因为有许多类似的功能,只是算法、结构或数据格式不同。在 man page 的末尾有一个 Description 部分,其中对它们进行了解释,删除了每个变体的细节。但是,是的,如果没有好的教程或示例,很难找到它。