我有一个仅包含RSA密钥公开部分的EVP_PKEY。我从DER编码的SubjectPublicKeyInfo结构中提取了公共(public)部分。这就是我现在所拥有的:

unsigned char publicKey[] = {0x30, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, ...}
size_t publicKeyLength = 92;
unsigned char* publicKeyCopy = new unsigned char[publicKeyLength];
memcpy(publicKeyCopy, publicKey, publicKeyLength);

RSA *rsa;
rsa = d2i_RSA_PUBKEY(NULL, (unsigned char const **) &pubKey, pubKeyLen);
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pkey, rsa);

我知道您可以使用RSA_check_key to verify a RSA private key,但是文档说“它不适用于仅填充了模数和公共(public)指数元素的RSA公共(public)密钥”。

因此,是否可以在没有私有(private)部分的情况下验证密钥?因为如您所见,我只有EVP_PKEY的公共(public)部分。我想知道,这可能吗?您会在EVP_PKEY的公开部分中验证什么?

您可以看到Programmatically verify a X509 certificate and private key match这个问题的答案,但此处的完整密钥已通过验证(私有(private)和公共(public)部分)。

当心
此问题中张贴的原始代码有错误。这是因为内部d2i_RSA_PUBKEY使用d2i_PUBKEYd2i_PUBKEY使用d2i_X509_PUBKEY(在x_pubkey.c中)。如果阅读documentation for d2i_X509,您将看到下一个“警告:必须使用临时变量。一个常见的错误是试图直接使用缓冲区...”。
因此,更正后的代码将不得不使用publicKeyCopy的临时副本,使用之后,您可以安全地删除publicKeyCopy:

最佳答案



我将对此发表评论,并向您展示如何处理。

unsigned char publicKey[] = {0x30, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, ...}
size_t publicKeyLength = sizeof(publicKey);

unsigned char* t = publicKey;
rsa = d2i_RSA_PUBKEY(NULL, &t, pubKeyLen);

在内部,临时指针t递增,因此浪费了。如果一切正常,它将指向缓冲区之后的某个位置。函数执行后,您应该找到的是(size_t)t - (size_t)publicKey == publicKeyLength

因为您使用了临时指针,所以原始指针publicKey仍然不错。如果内存中有连续的密钥,则可以使用t解析下一个密钥。

无需复制数据。

我认为第二种选择是使用内存BIOd2i_RSA_PUBKEY_bio。就像是:
BIO* bio = BIO_new_mem_buf(publicKey, (int)publicKeyLength);
ASSERT(bio != NULL);

RSA* rsa = d2i_RSA_PUBKEY_bio(bio, NULL);
ASSERT(rsa != NULL);

/* ... */

RSA_free(rsa);
BIO_free(bio);
get1会增加引用计数,因此您需要同时在freeEVP_PKEY*上调用RSA*

关于c++ - 验证OpenSSL中的RSA公钥?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30743245/

10-11 22:13
查看更多