从本期开始,记录一些在使用 OpenSSL 过程当中碰到的问题及解决办法app
在 Linux 下须要生成 pkcs12 文件,当即想到 OpenSSL。键入以下命令dom
~ # openssl pkcs12 -export -inkey clientkey.pem -in client.crt -out client.p12 No certificate matches private key ~ # openssl version OpenSSL 0.9.8j 07 Jan 2009
奇怪,明明 clientkey.pem 和 client.crt 是刚生成的配套文件,其中前者保存私钥,后者则是用户证书(包含公钥),怎么会出错?编辑器
因而切换到 Windows 平台再验证一番,虽然版本不一样,但仍然报错,只不过显示的错误信息不同函数
d:\>openssl pkcs12 -export -inkey clientkey.pem -in client.crt -out client.p12 WARNING: can't open config file: /usr/local/ssl/openssl.cnf Loading 'screen' into random state - done unable to load certificates d:\>openssl version WARNING: can't open config file: /usr/local/ssl/openssl.cnf OpenSSL 1.0.1f 6 Jan 2014
没办法,只得祭出调试器,到源码内部看个究竟。既然在 Windows 平台,就用顺手的 Visual Studio。打开(之前创建的)OpenSSL 解决方案(OpenSSL 版本号 1.0.1f),切换到 Debug 配置,确保该配置实际包含【-Zi】调试选项。spa
准备下断点,该在哪里下呢?调试
因为错误信息为 unable to load certificates ,其中过程确定涉及到证书加载函数,因此应该是 load_cert(不要问我为何知道,由于我熟悉^_^)。若是不熟悉,能够在 Source Insight 中用 F7 调出【Browse Project Symbols】对话框,输入猜想的关键字,好比 load/certificate 等,也能找到 load_cert 函数。code
反正不论如何,找到了怀疑函数 load_cert。在 Visual Studio 中新建此函数的断点,并在 IDE 中配置好命令参数和工做目录。F5 启动,果真命中,说明成功了一半。继续跟踪,最后获得出错的位置以下(位于文件 crypto\pem\pem_lib.c 中)orm
695 696 buf[254]='\0'; 697 for (;;) 698 { 699 i=BIO_gets(bp,buf,254); 700 701 if (i <= 0) 702 { 703 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE); 704 goto err; // <-- 【在此处出错,并跳出】 705 } 706
出错的调用栈为blog
openssl.exe!main
openssl.exe!do_cmd
openssl.exe!pkcs12_main
openssl.exe!load_certs
openssl.exe!load_certs_crls
libeay32.dll!PEM_X509_INFO_read_bio
libeay32.dll!PEM_read_biossl
自底向上逐个切换调用栈,查看是哪里引起了问题,结果在 pkcs12_main 函数(文件 apps\pkcs12.c)中,发现以下一处调用
461 462 /* Load in all certs in input file */ 463 if(!(options & NOCERTS)) 464 { 465 certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, 466 "certificates"); // <-- 【以 PEM 格式加载证书】 467 if (!certs) 468 goto export_end; 469
原来证书要求以 PEM 格式加载,回过头用文本编辑器打开 client.crt。果真,此文件是 DER 格式的。
名存实亡,天然是要出问题的。
缘由知道了,解决办法也当即有了。使用以下命令将证书转为 PEM 格式
d:\>openssl x509 -in client.crt -inform der -out client.pem
而后再执行一次 pkcs12 命令
d:\>openssl pkcs12 -export -inkey clientkey.pem -in client.pem -out client.p12
问题获得解决。
天然想到,难道 pkcs12 命令就不提供 -inform 的格式转换选项?运行命令【openssl pkcs12 ?】,能够看到确实没有提供 -inform 选项,看来仍是有改进的空间。