從本期開始,記錄一些在使用 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 選項,看來仍是有改進的空間。