2014年2月17日 星期一

[Solution] libcurl load certificate key failed (Unable to load client key -8178)

原因如下,如果預設的curl使用的SSL是NSS而非OpenSSL,而generate key file的方式是

openssl req -newkey rsa:1024 -keyout -keyform PEM -out -outform PEM

這邊 -newkey 產生出來的key file不能被NSS所解開 (Ref: BUG curl unable to load openssl encrypted private key),所以會產生-8178的錯誤
Description of problem:
When creating private keys using `openssl req -newkey` utility, 
the resulting private key file is base64 encoded, encrypted PKCS#8 file, 
with header:
-----BEGIN ENCRYPTED PRIVATE KEY-----

curl is unable to load such private keys. Reporting
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* warning: ignoring value of ssl.verifyhost
* Unable to load client key -8178.
* NSS error -8178
* Closing connection #0

When the file is re-encrypted using `openssl rsa -des3`, 
and has the following header:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,6840FC7927BDBA5E

curl is able to load the file successfully.



解法有兩個
1.不要用openssl的-newkey utility產生key file,用下面的方式產生

I spent a good portion of the day yesterday trying to get curl to authenticate with a web service using a client certificate specified with –cert and –key options. First, I created the certificate using
openssl req -nodes -newkey rsa:2048 -keyout client.key -out client.csr Then I had the csr signed and saved it as client.crt. Next, I tried to use the certificate using
curl -v --cert ./client.crt --key ./client.key -d @filetopost https://url/to/post/to Every time I did this I always got the following error.
Unable to load client key -8178 Searching the web did not turn up anything useful so I started playing with alternatives. I found that if I created the key and csr separately with
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr

2. 如下,簡單說就是重build libcurl with openssl(--with-ssl)

将centos6的curl ssl版本(NSS)替换成openssl,解决Unable to load client key -8178的错误问题 

在centos 6.2的系统里面的curl支持的https是nss版本的,而不是openssl的,所以在php使用curl访问https的时候会报Unable to load client key -8178的错误,在google group里面找到了灵感,也是curl和https的,里面说倒是curl的问题:
https://groups.google.com/forum/?fromgroups=#!topic/pongba/sgMYM9dGI7k


根据链接里面说的,去官网下载了一个最新版本(curl-7.28.1.tar.gz)的curl,来进行源码编译。
编译的依赖,openssl和openssl-devel。
编译方法和其他软件类似,步骤如下:
去到源码目录:curl-7.28.1
./configure --without-nss --with-ssl && make &&make install 即可完成编译。


然后是把curl的lib添加到PATH中,这个也是在google group里面说到的。
echo "/usr/local/lib" >> /etc/ld.so.conf && ldconfig


此时,通过命令行运行php调用curl 带证书访问web的php程序可以正常了。但是通过web界面还是之前那个Unable to load client key -8178 问题,需要重新编译php。


ldconfig
 
[root @test /root]# ldconfig [-f conf] [-C cache] [-p]
參數說明:
-f conf :使用 conf 作為 libarary 函式庫的取得,而不以 /etc/ld.so.conf 為預設值
-C cache:使用 cache 作為快取暫存的函式庫資料,而不以 /etc/ld.so.cache 為預設值
-p   :列出目前有的所有函式庫資料內容(在 /etc/ld.so.cache 內的資料!)
範例:
[root @test /root]# ldconfig -p
333 libs found in cache `/etc/ld.so.cache'
        libz.so.1 (libc6) => /usr/lib/libz.so.1
        libz.so (libc6) => /usr/lib/libz.so
        libxsltbreakpoint.so.1 (libc6) => /usr/lib/libxsltbreakpoint.so.1
        libxslt.so.1 (libc6) => /usr/lib/libxslt.so.1
        libxrx.so.6 (libc6) => /usr/X11R6/lib/libxrx.so.6
        libxrx.so (libc6) => /usr/X11R6/lib/libxrx.so
........
[root @test /root]# more /etc/ld.so.conf
/usr/kerberos/lib
/usr/X11R6/lib
[root @test /root]# ldconfig  <==以 /etc/ld.so.conf 的內容進行函式庫的重建( /etc/ld.so.cache )
說明:
系統預設的函式庫都是由 ldconfig 設定後寫入 /etc/ld.so.cache 當中!然後供系統來讀取使用!那麼您如何知道目前的函式庫有多少呢?呵呵!使用 ldconfig 就可以知道啦!以 ldconfig -p 可以列出 /etc/ld.so.cache 的內容呢!那麼 /etc/ld.so.conf 又是什麼呢?!很簡單,那就是『目前你的系統中主要的函式庫放置的目錄』,以上式為例,則主要的 XFree86 函式庫放置在 /usr/X11R6/lib 當中,另外還有常用的 kerberos 的函式庫也擺在其中!如果您的其他函式庫需要寫入系統中,讓系統可以很快的找到該函式庫而予以取用的話,那麼將你所安裝的套件(通常是 tarball 的套件)所產生的 lib 目錄,給他寫到 /etc/ld.so.conf 這個檔案中,然後再以 ldconfig 重新建立 /etc/ld.so.cache 即可!

沒有留言: