验证OpenSSL中的RSA公钥? [英] Verify a RSA public key in OpenSSL?
问题描述
我有一个仅包含RSA密钥公开部分的EVP_PKEY.我从DER编码的SubjectPublicKeyInfo结构中提取了公共部分.这就是我现在拥有的:
I have an EVP_PKEY with only the public part of a RSA key. I extracted the public part from a SubjectPublicKeyInfo structure in DER encoding. This is what I have now:
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来验证RSA私钥但是文档说"它不适用于仅填充了模数和公共指数元素的RSA公钥".
I know that you can use RSA_check_key to verify a RSA private key but the docs say that "It does not work on RSA public keys that have only the modulus and public exponent elements populated".
那么,可以在没有私有部分的情况下验证密钥吗?因为如您所见,我只有 EVP_PKEY的公共部分.我不知道,这有可能吗?您会在EVP_PKEY的公开部分中验证什么?
So, is it possible to verify a key without the private part? Because as you can see I have only the public part of the EVP_PKEY. I wonder, is this even possible? What would you verify in a public part of an EVP_PKEY?
您可以看到此问题的答案以编程方式验证X509证书和私钥匹配,但此处的完整密钥已通过验证(私钥和公钥).
You can see the answer for this question Programmatically verify a X509 certificate and private key match but there the full key is validated (private and public parts).
当心
此问题中发布的原始代码有错误.这是因为内部d2i_RSA_PUBKEY
使用d2i_PUBKEY
,而d2i_PUBKEY
使用d2i_X509_PUBKEY
(在 x_pubkey.c 中).如果您阅读d2i_X509的文档,您将看到下一个警告:必须使用临时变量.一个常见的错误是试图直接使用缓冲区..." .
因此,更正后的代码将必须使用publicKeyCopy
的临时副本,使用后,您可以安全地删除publicKeyCopy
:
Beware
The original code posted in this question has a BUG. This is because internally d2i_RSA_PUBKEY
uses d2i_PUBKEY
and d2i_PUBKEY
uses d2i_X509_PUBKEY
(in x_pubkey.c). If you read the documentation for d2i_X509 you will see the next "WARNING: The use of temporary variable is mandatory. A common mistake is to attempt to use a buffer directly...".
So the corrected code will have to use a temporary copy of publicKeyCopy
and after the use you could safely delete publicKeyCopy
:
推荐答案
借助@jww在此答案中 https://stackoverflow.com/a/29885771/2692914 .我想出了这个解决方案,希望可以:
With the help of @jww in this answer https://stackoverflow.com/a/29885771/2692914. I came up with this solution, I hope it is ok:
bool isValidPublicKeyOnly(EVP_PKEY *pkey) {
//EVP_PKEY_get_type from https://stackoverflow.com/a/29885771/2692914
int type = EVP_PKEY_get_type(pkey); //checks nullptr
if (type != EVP_PKEY_RSA && type != EVP_PKEY_RSA2) {
//not RSA
return false;
}
RSA *rsa = EVP_PKEY_get1_RSA(pkey);
if (!rsa) {
return false;
}
bool isValid = isValidRSAPublicKeyOnly(rsa);
RSA_free(rsa);
return isValid;
}
bool isValidRSAPublicKeyOnly(RSA *rsa) {
//from rsa_ameth.c do_rsa_print : has a private key
//from rsa_chk.c RSA_check_key : doesn't have n (modulus) and e (public exponent)
if (!rsa || rsa->d || !rsa->n || !rsa->e) {
return false;
}
//from http://rt.openssl.org/Ticket/Display.html?user=guest&pass=guest&id=1454
//doesnt have a valid public exponent
return BN_is_odd(rsa->e) && !BN_is_one(rsa->e);
}
这篇关于验证OpenSSL中的RSA公钥?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!