2014/03/26

2014-03-26:curl: (58) unable to set private key file

クライアント証明書を必要とするとある web API を curl 使って叩こうとして、送られてきた p12 ファイルからクライアント証明書を作ったはいいものの、そのクライアント証明書を curl の引数で渡して API 叩こうとしたところでタイトルのエラーが出てはまったというオハナシ。
この手の問題って年1弱な頻度でぶつかってる気がするんだけど、低頻度なだけにいろいろ覚えてなくて、毎度似たような調べ物をして記憶を取り戻してる感じなのよね。
自分の行動の時系列を追っているので、同様の問題にぶち当たって「結論だけ知りたい」方は、さくっとページ送って最後の方を見てください。

まず、.p12 ファイルからクライアント証明書な .pem を作った。

$ openssl pkcs12 -in hoge.p12 -out client.pem

で、これを使って curl で API を叩くんだけど、

$ /usr/bin/curl -E ./client.pem:xxxx -X POST -H 'Content-type: text/xml' -d 'aho' https://dokkano/api
curl: (58) unable to set private key file: ‘./client.pem’ type PEM

あれ? client.pem のパスワード間違ってる?
コマンドラインに入れずに、プロンプトさせて、手動で打ってみても同じ。

$ /usr/bin/curl -E ./client.pem:xxxx -X POST -H 'Content-type: text/xml' -d 'aho' https://dokkano/api
Enter PEM pass phrase: ←ここでパスワードを入力
curl: (58) unable to set private key file: './client.pem' type PEM

おかしいな、ほんとにパスワードが違うんだろうか。。。
-text で中身見れるかの確認をしてみよう。

$ openssl rsa -text -in client.pem
Enter pass phrase for client.pem: ←正しいパスワードを入力
Private-Key: (2048 bit)
modulus:
    00:aa:bb:cc:dd:ff:01:02:03:04:05:06:07:08:09:
    12:34:56:78:9a:bc:de:f0:11:22:33:44:55:66:77:
    ....
 
$ openssl rsa -text -in client.pem
Enter pass phrase for client.pem: ←わざと間違ったパスワードを入力
unable to load Private Key
22705:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:325:
22705:error:23077074:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 cipherfinal error:p12_decr.c:97:
22705:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:p12_decr.c:123:
22705:error:0907B00D:PEM routines:PEM_READ_BIO_PRIVATEKEY:ASN1 lib:pem_pkey.c:125:

やっぱり合ってるじゃん。。。

なにがおかしいんだろう、とググって情報探してみたら、curl のメーリングリストのアーカイブ に、「秘密鍵とクライアント証明書とCA証明書をばらばらにしてやったら上手くいったよ!」というのを発見。
これをヒントに .pem を作り直してやってみる。

$ openssl pkcs12 -in hoge.p12 -out client.pem -clcerts
$ /usr/bin/curl -E ./client.pem:xxxx -X POST -H 'Content-type: text/xml' -d 'aho' https://dokkano/api

manuke

うまくいった!

.pem に一緒に入ったCA証明書がイマイチで撥ねられたってことなのかなぁ。
正直、”unable to set private key file” だけじゃ分からないよ!と思う。
クライアント証明書のパスワードが間違ったときと同じエラーメッセージだしね。