我有一个仅包含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_PUBKEY
而d2i_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
解析下一个密钥。无需复制数据。
我认为第二种选择是使用内存
BIO
和d2i_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
会增加引用计数,因此您需要同时在free
和EVP_PKEY*
上调用RSA*
。关于c++ - 验证OpenSSL中的RSA公钥?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30743245/