私が愛した openssl (PKI 編 その 2)

id:blooper:20120907 の続きです。参考図書などはそっちを見て頂くのが宜しいのではないかと。

pkcs12

PKCS#12 形式のファイルを扱います。PKCS に関しては wikipedia:PKCS を、でした。昔は PFX と言っていたらしく、Windows だと今でも拡張子を .pfx としています。.p12 は、いけるんだっけ? 何の為の形式かっつーと、証明書とそのペアの秘密鍵を格納して、秘密鍵パスフレーズで暗号化します。その他認証局の証明書も格納できます。例えば、Windows の CryptoAPI とか Java の keytool とか IBM の iKeyman とかは、RSA 秘密鍵をそのままではインポートできなくて、PKCS#12 形式にして証明書と一緒にインポートしてあげる必要があります、たしか。

先ずは作ってみます

$ openssl req -new -x509 -newkey rsa:2048 -keyout abc.key -out abc.crt
$ openssl pkcs12 -export -inkey abc.key -in abc.crt -out abc.p12
Enter pass phrase for abc.key:
Enter Export Password:
Verifying - Enter Export Password:

自己署名証明書を RSA2048 で作って鍵を abc.key 証明書を abc.crt に保存したあと、その 2 つのファイルを abc.p12 としてまとめました。

$ openssl pkcs12 -export -inkey abc.key -in abc.crt -out abc.p12 -certfile google.crt
||
と -certfile を指定すると中間証明書なども格納できます、が、全く検証せずにとりあえずつっこむみたいです。www.google.com から取ってきた証明書つっこんでどうするんだっつー。

で、中身を見るには、
>|sh|
$ openssl pkcs12 -in abc.p12 -nodes | grep BEGIN
Enter Import Password:
MAC verified OK
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----BEGIN PRIVATE KEY-----

ふお、MAC を検証してる。MAC で完全性を確保してるんですね、知らなかった! -nodes で出力される秘密鍵パスフレーズをつけないでいます。これで abc.crt, google.crt, abc.key が abc.p12 から抜き出せています。

$ openssl pkcs12 help
(snip)
-nocerts      don't output certificates.
-clcerts      only output client certificates.
-cacerts      only output CA certificates.
-nokeys       don't output private keys.

などでエンド証明書だけとか認証局証明書だけとか、鍵を出す出さないとか、コントロールできます。

verify

あぁ、検証。証明書を検証します。その証明書が正当なものかどうかを検証するわけですが、正当って何でしょうねぇ。

正解は RFC 5280 などで理解しなくてはいけませんが、最低限

  • 有効期間内のものかどうか
  • 信用している (自己署名) 証明書まで署名のチェインを辿れるか
  • 失効されていないか
  • 証明書ポリシーなど認証局の定めた制限をパスしているか

など確認しなくてはいけません。この最後の奴が何とも面倒臭そうです。というか特に最後の部分は検証するときの解釈もあるので解釈を定めてからでないと検証の結果も一意には定まりません。なので面倒なのでちょっと放置。

とりあえず、証明書を取ってきましょう。

$ openssl s_client -connect www.google.com:443 -showcerts < /dev/null
(snip)
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
   i:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
-----BEGIN CERTIFICATE-----
MIIDITCCAoqgAwIBAgIQT52W2WawmStUwpV8tBV9TTANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMTEwMjYwMDAwMDBaFw0x
MzA5MzAyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw
FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEA3rcmQ6aZhc04pxUJuc8PycNVjIjujI0oJyRLKl6g2Bb6YRhLz21ggNM1QDJy
wI8S2OVOj7my9tkVXlqGMaO6hqpryNlxjMzNJxMenUJdOPanrO/6YvMYgdQkRn8B
d3zGKokUmbuYOR2oGfs5AER9G5RqeC1prcB6LPrQ2iASmNMCAwEAAaOB5zCB5DAM
BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl
LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF
BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw
Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0
ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF
AAOBgQAhrNWuyjSJWsKrUtKyNGadeqvu5nzVfsJcKLt0AMkQH0IT/GmKHiSgAgDp
ulvKGQSy068Bsn5fFNum21K5mvMSf3yinDtvmX3qUA12IxL/92ZzKbeVCq3Yi7Le
IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q==
-----END CERTIFICATE-----
 1 s:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
-----BEGIN CERTIFICATE-----
MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV
UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi
bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw
MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD
QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx
PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g
5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo
3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG
A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX
BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov
L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG
AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF
BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB
BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc
q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR
bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv
-----END CERTIFICATE-----
(snip)

2 枚出てきたのでそれぞれ server.crt と intermediate.crt として保存します。

早速 verify

$ openssl verify server.crt 
server.crt: C = US, ST = California, L = Mountain View, O = Google Inc, CN = www.google.com
error 20 at 0 depth lookup:unable to get local issuer certificate

失敗してしまいました。認証局の証明書を信頼する証明書として指定してやらなくてはいけません。

$ openssl verify -CAfile intermediate.crt server.crt
server.crt: OK

成功しました。でもでも、CRL とかもチェックしてみたいものです。

$ openssl x509 -noout -text < server.crt | egrep -i crl
            X509v3 CRL Distribution Points: 
                  URI:http://crl.thawte.com/ThawteSGCCA.crl
$ curl http://crl.thawte.com/ThawteSGCCA.crl | openssl crl -inform der >> intermediate.crt 

server.crt の中身から CRL にマッチする行を探したら http://crl.thawte.com/ThawteSGCCA.crl にあることが分かったので、curl で取ってきて openssl crl で受けて DER から PEM にして intermediate.crl に追記しました。

$ openssl verify -crl_check -CAfile intermediate.crt server.crt
server.crt: OK

成功しました。あと、例えば証明書の用途も確認できます。

$ openssl verify -CAfile intermediate.crt -purpose sslserver server.crt
server.crt: OK
$ openssl verify -CAfile intermediate.crt -purpose timestampsign server.crt
server.crt: C = US, ST = California, L = Mountain View, O = Google Inc, CN = www.google.com
error 26 at 0 depth lookup:unsupported certificate purpose
OK

OK って言っちゃうの? でも error 26 が出てますね。man verify すると

       26 X509_V_ERR_INVALID_PURPOSE: unsupported certificate purpose
           the supplied certificate cannot be used for the specified purpose.

と説明があります。他のコードも説明があります。

では、intermediate.crt は信じていいのか? intermediate.crt の Issuer は

$ openssl x509 -in intermediate.crt -noout -issuer
issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

という証明書で、これは自己署名されているルート証明書でした。

$ openssl x509 -in intermediate.crt -noout -issuer_hash
415660c1

上の名前 (の DER エンコーディングされたもの) のハッシュを取ると 415660c1 なのですが、

$ ls -l /etc/ssl/certs/415660c1*
lrwxrwxrwx 1 root root 59 2011-12-27 01:01 /etc/ssl/certs/415660c1.0 -> Verisign_Class_3_Public_Primary_Certification_Authority.pem
$ openssl x509 -in /etc/ssl/certs/415660c1* -noout -issuer -subject
issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
subject= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

ハッシュ値.0 という名前でシンボリックリンクが作られています。これは -CApath ファイルで指定するディレクトリに証明書を保存しておく約束で、指定されたディレクトリからハッシュ値を使って使うべき証明書を探すわけです。なので

$ openssl verify -CApath /etc/ssl/certs intermediate.crt
intermediate.crt: OK

と正しい証明書を見つけてくれて OK と出ました。

$ openssl x509 -in intermediate.crt -noout -text | egrep -i crl
                Certificate Sign, CRL Sign
            X509v3 CRL Distribution Points: 
                  URI:http://crl.verisign.com/pca3.crl
$ curl -s http://crl.verisign.com/pca3.crl | openssl crl -inform der > pca3.crl
$ openssl verify -CApath /etc/ssl/certs -CAfile pca3.crl intermediate.crt
intermediate.crt: OK

と、-CApath で信頼する証明書のリストを、-CAfile で CRL を指定するなんてこともできます。

あとは、-policy_check とかのオプションもあります。

pkcs7

PKCS#7 というのは、wikipedia:wiki/PKCS によると

PKI の下でメッセージを署名や暗号化するのに使用される。証明書の配布のためにも用いられる(例えば、PKCS #10メッセージの応答として)。

とのことですが、例えば Windows 用に複数の中間証明書を配布する為などに使われています。拡張子は p7b すかね。google:filetype:p7b Google すげぇな。

$ openssl pkcs7 -in my.p7b -print_certs

のようにすると、中に入っている証明書を取り出すことができます。

crl2pkcs7

名前に騙されてはいけなくて、man にもあるように "Create a PKCS#7 structure from a CRL and certificates." と CRL だけでなく証明書も使えます。

とりあえず CRL をつっこんでみると

$ openssl crl2pkcs7 -in ThawteSGCCA.crl -inform der |head -n 2
-----BEGIN PKCS7-----
MIIZeAYJKoZIhvcNAQcCoIIZaTCCGWUCAQExADALBgkqhkiG9w0BBwGgAKGCGUsw

確かに変換されていますし、

$ openssl crl2pkcs7 -nocrl -certfile server.crt -certfile intermediate.crt | openssl pkcs7 -noout -print_certs
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer=/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA

subject=/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
issuer=/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

と、証明書が詰まった PKCS#7 形式も作れます。上の例だと 2 枚の証明書をつっこんでいます。

ocsp

CRL はファイルなので、常時更新されているかも分からず、基本的にオフラインで利用されることが想定されていました。それじゃダメでしょ、ってことでオンラインの失効情報確認の仕組みが OCSP (Online Certificate Status Protocol) です。OCSPRFC 2560 などで定義されていて、

  • リクエストのバイナリ形式
  • レスポンスのバイナリ形式
  • リクエスト方法
  • レスポンス方法

などが定義されています。

ocsp はリクエストやレスポンスの生成、OCSP クライアント、OCSP サーバになれる何でも屋さんなのですが、失効情報など管理するにあたって沢山のファイルを利用します。ca と ocsp は仲良しさんなので、一緒に使うことを想定されてるみたいです。

サーバ機能に関しては、HTTP サーバなわけですが、貧弱すぎたり返事が上手く取ってこれなかったりで、結局 Apache か nginx に proxy させて CGI か何かで ocsp 呼んでレスポンス返してみた気がします。今はどうなんだろうな。

man ocsp の EXAMPLE 見れば分かるんですが、というともぉ自分の存在意義を否定し始めてますが

$ openssl ocsp -issuer intermediate.crt -cert server.crt -reqout req.der

で、OCSP リクエストを生成します。このリクエストをサーバに送りつけたいわけですが、

$ openssl x509 -in server.crt -noout -text | egrep -i ocsp
                OCSP - URI:http://ocsp.thawte.com

というわけで

$ openssl ocsp -issuer intermediate.crt -cert server.crt -url http://ocsp.thawte.com -resp_text -respout resp.der -CAfile intermediate.crt
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: C = ZA, O = Thawte Consulting (Pty) Ltd., CN = Thawte SGC OCSP Responder
    Produced At: Sep 11 18:03:43 2012 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: 1E9209AA713C794BCA1E931A0A61AD3FD0BA6083
      Issuer Key Hash: 3B349A709173B28A1B0CF4E937CDB370329E1854
      Serial Number: 4F9D96D966B0992B54C2957CB4157D4D
    Cert Status: good
    This Update: Sep 11 18:03:43 2012 GMT
    Next Update: Sep 18 18:03:43 2012 GMT

    Signature Algorithm: sha1WithRSAEncryption
        1a:73:a7:22:9a:ec:22:6a:d0:b8:28:7c:a0:01:0f:37:2a:5c:
        69:e3:2d:c1:6f:3f:98:53:1a:cd:bc:ae:de:dc:19:9b:47:bd:
        77:ef:32:13:23:ef:28:da:a1:56:bf:8b:00:f9:96:25:04:f2:
        09:c5:6e:93:ff:61:28:2d:46:65:e7:fc:d6:e0:82:c4:64:fc:
        ec:59:12:5f:02:ce:76:fa:c6:8e:00:ef:d0:a5:34:a5:26:b9:
        4c:6b:39:46:49:f9:3a:19:ad:84:f2:95:de:0d:2b:82:88:49:
        d3:18:2e:0f:97:69:36:97:3f:76:53:c3:2e:65:ce:60:81:e4:
        a0:a3
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            01:8b:4d:61:4e:17:e0:9b:95:c2:05:bc:01:24:1a:38
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=ZA, O=Thawte Consulting (Pty) Ltd., CN=Thawte SGC CA
        Validity
            Not Before: Aug 17 00:00:00 2012 GMT
            Not After : Nov 15 23:59:59 2012 GMT
        Subject: C=ZA, O=Thawte Consulting (Pty) Ltd., CN=Thawte SGC OCSP Responder
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:cf:4f:fa:fd:ba:ba:3c:05:6b:03:99:fe:3c:2f:
                    62:62:15:f6:84:89:09:f4:06:44:3c:d2:69:b1:1f:
                    11:1e:18:21:02:bb:22:cf:79:b7:e7:81:4c:1c:92:
                    76:35:64:87:ca:4b:86:5f:36:2b:9b:a0:a8:56:29:
                    08:f7:ff:a8:38:e3:73:4a:bf:f9:87:50:54:12:12:
                    9d:c4:2e:82:ad:3d:7e:21:7a:cd:68:af:9a:d2:d2:
                    04:a6:79:10:4d:dd:c7:11:01:91:f5:c1:39:f8:6c:
                    a5:14:52:19:b3:be:62:9a:4c:59:89:07:34:ce:8e:
                    5c:69:ca:9b:98:b8:0c:88:39
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            X509v3 Extended Key Usage: 
                OCSP Signing
            X509v3 Key Usage: 
                Digital Signature
            OCSP No Check: 

            X509v3 Subject Alternative Name: 
                DirName:/CN=OCSP8-TGV7-376
    Signature Algorithm: sha1WithRSAEncryption
        13:09:e4:dd:fa:1f:7c:e5:7b:15:d6:d6:5a:8e:43:cb:f8:c2:
        e3:b5:fc:63:42:6a:81:77:56:9b:a3:42:2c:f5:b2:b2:35:cd:
        aa:ba:30:61:f2:ee:02:e1:22:bc:37:52:05:69:c1:b9:c9:42:
        73:80:1e:ea:93:d4:99:38:8d:1e:5c:06:38:66:91:be:45:c9:
        74:3c:38:78:71:dd:3e:55:4b:32:af:60:d0:0d:c6:a3:77:05:
        d4:05:f3:b4:86:26:6f:81:9b:27:7c:71:fc:41:57:f8:9c:e6:
        1e:11:56:8c:65:fb:1b:11:73:73:f7:b5:ce:82:85:9d:6d:51:
        b7:1d
-----BEGIN CERTIFICATE-----
MIICkTCCAfqgAwIBAgIQAYtNYU4X4JuVwgW8ASQaODANBgkqhkiG9w0BAQUFADBM
MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg
THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMjA4MTcwMDAwMDBaFw0x
MjExMTUyMzU5NTlaMFgxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3dGUgQ29u
c3VsdGluZyAoUHR5KSBMdGQuMSIwIAYDVQQDExlUaGF3dGUgU0dDIE9DU1AgUmVz
cG9uZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPT/r9uro8BWsDmf48
L2JiFfaEiQn0BkQ80mmxHxEeGCECuyLPebfngUwcknY1ZIfKS4ZfNiuboKhWKQj3
/6g443NKv/mHUFQSEp3ELoKtPX4hes1or5rS0gSmeRBN3ccRAZH1wTn4bKUUUhmz
vmKaTFmJBzTOjlxpypuYuAyIOQIDAQABo2gwZjAJBgNVHRMEAjAAMBMGA1UdJQQM
MAoGCCsGAQUFBwMJMAsGA1UdDwQEAwIHgDAPBgkrBgEFBQcwAQUEAgUAMCYGA1Ud
EQQfMB2kGzAZMRcwFQYDVQQDEw5PQ1NQOC1UR1Y3LTM3NjANBgkqhkiG9w0BAQUF
AAOBgQATCeTd+h985XsV1tZajkPL+MLjtfxjQmqBd1abo0Is9bKyNc2qujBh8u4C
4SK8N1IFacG5yUJzgB7qk9SZOI0eXAY4ZpG+Rcl0PDh4cd0+VUsyr2DQDcajdwXU
BfO0hiZvgZsnfHH8QVf4nOYeEVaMZfsbEXNz97XOgoWdbVG3HQ==
-----END CERTIFICATE-----
WARNING: no nonce in response
Response verify OK
server.crt: good
	This Update: Sep 11 18:03:43 2012 GMT
	Next Update: Sep 18 18:03:43 2012 GMT

証明書付きで結果を返してくれています。"server.crt: good"!! intermediate.crt を二回指定していますが、-CAfile で指定している方はレスポンスの署名の確認用の証明書指定だそうです。

サーバの方は面倒なので省略。サーバの方をやるなら ca を先に説明するべきだな!

ca

CA は Certification Authority の頭文字、これは認証局のことです。簡単な認証局を運用できるような便利な仕組みを用意してくれています。CA を運用するには

  • 認証局の証明書
  • 認証局秘密鍵
  • CSR への署名
    • 有効期限の設定
    • シリアルの割当
    • 証明書拡張の付与
  • 発行した証明書とそのステータスの管理
  • CRL の作成

などがあるので、これらを設定ファイルやオプションで指定して実行できるようになっています。

これも、面倒だから省略。気が向いたら更新するかもね! っていうかその気にさせてよ!!