我意识到类似的问题已经在其他地方,在SO和人们的网页上得到了解决。但是,这些解决方案不起作用。在我的单人尝试失败后,我已经尝试了各种各样的组合。
背景: 我有一个包含私钥(通常是RSA),CSR和X509客户端证书的文件。这些结构都是PEM形式。用户应该将这三个组件连接成一个文件。有时他们不会或者做得不正确 - 例如,他们会省略私钥,或者将证书放入两次,或者在不更新证书的情况下重新绑定私钥。我想在系统启动时检测到这些情况,并向用户指出他们为什么不联系密钥管理器服务器。
问题: 首先,我想验证证书是否与私钥对应。次要的兴趣是CSR对应于证书/私钥。
OpenSSL' rsa'和' x509'命令行实用程序确实验证了我的示例测试文件,并且该文件允许我的客户端联系密钥管理器服务器。这些都是相当好的有效性指标。
检查OpenSSL模块' rsa.c',我看到' pubout'参数结束了 - 我认为 - PEM_write_bio_RSA_PUBKEY。在OpenSSL 1.0.2f和OpenSSL 1.1.0中,我找不到PEM_write_bio_RSA_PUBKEY的源代码......但rsa.c显然编译和链接,VS调试器将我带入一些汇编代码,所有这些都表明这是某种动态制造的例程,链接器正在管道中;如果是的话,这似乎并不是特别开源的。对我来说,但你去了。请记住,不必从统一文件中手动提取结构以使OpenSSL实用程序正常工作 - 实用程序会在文件中找出它们感兴趣的内容(无论是rsa,req还是x509)以及他们玩的是什么。
实现: 例程' X509_verify'需要X509结构和EVP_PKEY结构。 EVP_PKEY结构应该是公钥(尽管我引用的其中一个网页有作者声称它是私钥,可能作为RSA密钥可以互换,只要他们一直互相交换......但是因为我无法获得应该工作的东西,工作,我不能说出一种方式。
如果' X509_verify(...)'当所有人拥有私钥和证书时,必须使用私钥,公钥必须从私钥中提取,并提供给' X509_verify(...)'在EVP_PKEY结构中。
这是我尝试过的众多方法中的一种。这个实际上使用非空指针进入X509_verify调用,但不幸的是总是返回一个 验证为零。我跳过了CheckError调用,null检查和各种“免费”:
// Retrieve the BIO allocated earlier for the file, and
// extract the private key...
EVP_PKEY * pPKEYPrivateKey = PEM_read_bio_PrivateKey(GetBIO(), NULL, NULL, NULL);
int type = EVP_PKEY_type(pPKEYPrivateKey->type);
switch (type)
{
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
{
// Convert the EVP_PKEY private key structure to an
// RSA private key, then check it...
RSA * pRSAPrivateKey = EVP_PKEY_get1_RSA(pPKEYPrivateKey);
if (1 != RSA_check_key(pRSAPrivateKey))
{
...no good, exit, stage right...
}
// Using the RSA private key, extract and copy the
// public key into its own RSA structure...
RSA * pRSAPublicKey = RSAPublicKey_dup(pRSAPrivateKey);
// Get a PKEY area...
EVP_PKEY * pPKEYPublicKey = EVP_PKEY_new();
// Convert the public RSA key data into a EVP_PKEY structure...
int evtrc = EVP_PKEY_assign_RSA(pPKEYPublicKey, pRSAPublicKey);
// We now have the public key extracted into an EVP_PKEY
// structure (or do we?)...
int verifyrc = X509_verify(ipCertificate->GetX509(), pPKEYPublicKey);
// ...but the above call always returns zero...
if (1 != verifyrc
{
...
最佳解决方案是关键型不可知,我不必区分RSA或DSA,PEM或DER,或其他任何东西。但是,各种密钥类型和格式的隔离与我可以通过看起来像有效公钥指针的X509_verify调用一样接近。比较模数值的解决方法就是 - 因为,如果要验证事情的原因,为什么有X509验证函数?当然,验证功能本身可能正在比较模数值......在这种情况下,是否应检查模数值与手头的讨论无关。
我已经使用了RSA_PUBKEY函数,但这些函数总是返回一个空指针。由于我不知道他们在做什么,我无法弄清楚是什么错误。
另一种方法是从X509证书中提取公钥,并将其与从私钥中提取的公钥进行比较,但这似乎也是一种解决方法。另外,如果我没有做正确的事情,那我就再也没事了。
另一方面,完美是善的敌人。
要点: 有人会认为这不是任何形式的痕迹,并且这几乎是一种普通的日常程序检查 - 这个私钥是否与X509证书一致?即使我所拥有的东西似乎也因为那些平凡的东西而过于复杂。
如果某人善于提供解决方案,请先检查一下。相信但要验证。
并且:如果有人可以指向我的PEM_write_bio_RSA_PUBKEY源代码或PEM_write_bio_PUBKEY源代码,我怀疑这可能会让我感到困惑。也许
感谢。