以编程方式验证 SSL 证书
我知道这将是一篇很大的文章,但我想通过本质上给出它的所有细节来提出我面临的问题。
背景 我有一个应用程序,它触发 Firefox 获取 URL 数据并显示网页中所有组件的单个组件加载时间(如 Firebug)。但是,该应用程序不会自动验证 ssl 证书(即,如果证书错误,它就会卡住,因为没有用户手动接受/拒绝证书,而且这一切都是以编程方式完成的)。我需要通过在 Firefox 进程启动之前尝试验证站点的证书来解决此问题。
我的解决方案
我发现这段 C 代码可以在 C 中以编程方式验证 SSL 证书。我对其进行简要概述。这是 main() 方法:
SSL_library_init();
ERR_load_BIO_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
/* Set up the SSL context */
ctx = SSL_CTX_new(SSLv23_client_method());
/* Load the trust store - in this case, it's just a single
* certificate that has been created for testing purposes.
*/
if(! SSL_CTX_load_verify_locations(ctx,"certificate.pem",NULL))
{
fprintf(stderr, "Error loading trust store\n");
//ERR_print_errors_fp(stderr);
SSL_CTX_free(ctx);
return 0;
}
/* Setup the connection */
bio = BIO_new_ssl_connect(ctx);
/* Set the SSL_MODE_AUTO_RETRY flag */
BIO_get_ssl(bio, & ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* Create and setup the connection */
BIO_set_conn_hostname(bio, "mail.google.com:https");
fprintf(stderr, "Connecting to host ...\n");
if(BIO_do_connect(bio) <= 0)
{
fprintf(stderr, "Error attempting to connect: %d\n",BIO_do_connect(bio));
//ERR_print_errors_fp(stderr);
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
/* Retrieve the peer certificate */
fprintf(stderr, "Retrieving peer certificate\n");
if(getPeerCert(ssl, & peerCert) != X509_V_OK)
{
/* Can be changed to better handle a suspect certificate. However,
* for the purposes of this demonstration, we're aborting.
*/
fprintf(stderr, "Certificate verification error: %i\n",SSL_get_verify_result(ssl));
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
我省略了 getPeerCert() 方法的定义,因为它获取对等证书并使用 openssl 的方法进行验证。
另外,certificate.pem 是通过执行
但是,当我尝试运行此程序时,
Connecting to host ...
Retrieving peer certificate
Certificate verification error: 20
我无法理解为什么会发生这种情况,因为验证应该成功。对于我能得到的任何帮助,我将不胜感激并感到高兴。
更新1
我尝试使用open SSL命令并尝试从代码调用该命令,即
opensssl verify -CAfile ./ca-bundle.crt cert1...
但是我发现它验证内部和外部证书,它似乎也验证实际上应该是坏的证书(内部) (特别是错误的域证书)。我将非常感谢对此的任何见解。
I know this will be a huge post, but I wanted to present a problem that I am facing by essentially giving all the details of it.
Background
I have an application which triggers firefox to fetch URL data and present the individual component load time of all components in a web page (like Firebug). However the application does not validate ssl certs automatically (i.e it gets stuck up if there is a bad certificate as there is no user to manually accept/reject a certificate and it is all done programmatically). I need to solve this issue by trying to validate the site's certificate before the firefox process is started.
My solution
I found this bit of C code that does verification of SSL certs programmatically in C. I am giving a brief overview of it. this is the main() method:
SSL_library_init();
ERR_load_BIO_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
/* Set up the SSL context */
ctx = SSL_CTX_new(SSLv23_client_method());
/* Load the trust store - in this case, it's just a single
* certificate that has been created for testing purposes.
*/
if(! SSL_CTX_load_verify_locations(ctx,"certificate.pem",NULL))
{
fprintf(stderr, "Error loading trust store\n");
//ERR_print_errors_fp(stderr);
SSL_CTX_free(ctx);
return 0;
}
/* Setup the connection */
bio = BIO_new_ssl_connect(ctx);
/* Set the SSL_MODE_AUTO_RETRY flag */
BIO_get_ssl(bio, & ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* Create and setup the connection */
BIO_set_conn_hostname(bio, "mail.google.com:https");
fprintf(stderr, "Connecting to host ...\n");
if(BIO_do_connect(bio) <= 0)
{
fprintf(stderr, "Error attempting to connect: %d\n",BIO_do_connect(bio));
//ERR_print_errors_fp(stderr);
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
/* Retrieve the peer certificate */
fprintf(stderr, "Retrieving peer certificate\n");
if(getPeerCert(ssl, & peerCert) != X509_V_OK)
{
/* Can be changed to better handle a suspect certificate. However,
* for the purposes of this demonstration, we're aborting.
*/
fprintf(stderr, "Certificate verification error: %i\n",SSL_get_verify_result(ssl));
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
I am leaving out the getPeerCert() method's defenition as it gets the peer cert and verifies using openssl's methods.
Also the certificate.pem is a pem file obtained by following the steps for the solution to this question.
However When I try to run this i get
Connecting to host ...
Retrieving peer certificate
Certificate verification error: 20
I am unable to see why this should happen as the verification should succeed. I would be grateful and glad to any help that I can get.
Update 1
I tried using the open SSL command and tried calling the command from code i.e. the
opensssl verify -CAfile ./ca-bundle.crt cert1...
However I found that it validates internal and external certs, it also seemed to validate certs (internal) that should actually be bad (specifically bad domain certs). I would greatly appreciate any insight into this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看到这篇文章,但我还不知道如何以编程方式执行此操作。
http://www .herongyang.com/crypto/openssl_verify_2.html\
see this article, but I don't know yet how to do it programatically..
http://www.herongyang.com/crypto/openssl_verify_2.html\
您遇到的特定错误是
尝试输入 gmail 颁发者,而不是Gmail 证书,转换为certificate.pem。
另外,请确保您理解布鲁诺对您的问题的第一条评论。
The specific error you are are getting is
Try putting the gmail issuer, and not the gmail certificate, into certificate.pem.
Also, make sure you understand Bruno's first comment on your question.
用户CertificateFactory获取X509证书的实例并使用generateCertificate方法进行验证,这是java安全
cmd中的lib来验证证书
User CertificateFactory to get instance of X509 cert and validate using generateCertificate method this is lib in java security
cmd to verify cert