ラベル OpenSSL の投稿を表示しています。 すべての投稿を表示
ラベル OpenSSL の投稿を表示しています。 すべての投稿を表示

2012/09/28

SSL/TLSポートの試験にopenssl s_client・gnutls-cliを使う


通常のTCPポート試験には、nc(1)コマンドを使う(以前はtelnet(1)コマンドがよく使われていた)。例えば、POP(110/tcp)は、以下の様に試験できる。
[user01@rhel01 ~]$ nc localhost 110
+OK Dovecot ready.
USER user01
+OK
PASS password
+OK Logged in.
LIST
+OK 1 messages:
1 448
.
QUIT
+OK Logging out.
[user01@rhel01 ~]$

では、SSL/TLSで暗号化されたTCPポートのテストはどうすればよいか?
まず、openssl(1)コマンドを用いる方法がある。このopensslコマンドのサブコマンドs_clientに、接続先を指定するオプション「-connect host:port」を与えて試験すればよい。例えば、POP3S(995/tcp)は、以下の様に試験できる。
[user01@rhel01 ~]$ openssl s_client -connect localhost:pop3s
CONNECTED(00000003)
depth=0 /OU=IMAP server/CN=imap.example.com/emailAddress=postmaster@example.com
verify error:num=18:self signed certificate
verify return:1
depth=0 /OU=IMAP server/CN=imap.example.com/emailAddress=postmaster@example.com
verify return:1
---
Certificate chain
 0 s:/OU=IMAP server/CN=imap.example.com/emailAddress=postmaster@example.com
   i:/OU=IMAP server/CN=imap.example.com/emailAddress=postmaster@example.com
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICQzCCAaygAwIBAgIJALDUM09AsGlJMA0GCSqGSIb3DQEBBQUAMFgxFDASBgNV
<<略>>
Mk2FmzapbpeX11HSqprCX984Ofn00Ou8/AS2d9yEeJ/fsbB6UO9L8DZb0gL9nrkL
L7oDAsrwYg==
-----END CERTIFICATE-----
subject=/OU=IMAP server/CN=imap.example.com/emailAddress=postmaster@example.com
issuer=/OU=IMAP server/CN=imap.example.com/emailAddress=postmaster@example.com
---
No client certificate CA names sent
---
SSL handshake has read 1154 bytes and written 319 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 69F38BFB461D7E2CA1ED16CD1F7CA61B0CEEE69E9EB6AB64A45FDEC3BC4EE710
    Session-ID-ctx:
    Master-Key: 77544FE452E4FE2E1D735F023CD36BB5C8F6BD91BB62FB7A12C105144FB85A6F6FD2D2442B97F8DA96E753C21E7FB78A
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1348815266
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---
+OK Dovecot ready.
USER user01
+OK
PASS password
+OK Logged in.
LIST
+OK 1 messages:
1 448
.
QUIT
DONE
[user01@rhel01 ~]$

別法として、gnutls-cli(1)コマンドを使う方法もある。
[user01@rhel01 ~]$ gnutls-cli --port pop3s localhostResolving 'localhost'...
Connecting to '127.0.0.1:995'...
- Certificate type: X.509
 - Got a certificate list of 1 certificates.

 - Certificate[0] info:
 # The hostname in the certificate does NOT match 'localhost'.
 # valid since: Fri Sep 28 14:51:09 JST 2012
 # expires at: Sat Sep 28 14:51:09 JST 2013
 # fingerprint: E4:CB:D0:E4:F7:78:E8:59:20:45:0F:33:D4:4C:DB:01
 # Subject's DN: OU=IMAP server,CN=imap.example.com,EMAIL=postmaster@example.com
 # Issuer's DN: OU=IMAP server,CN=imap.example.com,EMAIL=postmaster@example.com


- Peer's certificate issuer is unknown
- Peer's certificate is NOT trusted
- Version: TLS 1.0
- Key Exchange: DHE RSA
- Cipher: AES 256 CBC
- MAC: SHA
- Compression: DEFLATE
- Handshake was completed

- Simple Client Mode:

+OK Dovecot ready.
USER user01
+OK
PASS password
+OK Logged in.
LIST
+OK 1 messages:
1 448
.
QUIT
+OK Logging out.
*** Fatal error: A TLS packet with unexpected length was received.
*** Server has terminated the connection abnormally.
[user01@rhel01 ~]$

なお、Red Hat系であれば、openssl(1)・gnutls-cli(1)両コマンドはそれぞれ、openssl・gnutls-utilsの両パッケージに含まれる。
[user01@rhel01 ~]$ rpm -qf $(which openssl)
openssl-0.9.8e-20.el5
openssl-0.9.8e-20.el5
[user01@rhel01 ~]$ rpm -qf $(which gnutls-cli)
gnutls-utils-1.4.1-3.el5_4.8
[user01@rhel01 ~]$

2007/03/05

NTP認証: ユニキャスト・公開鍵認証篇

NTP認証シリーズの第四回。今回は、ユニキャスト・公開鍵認証。

まずは、ドキュメントを読んでみる。FC5パッケージntpがインストールされていれば、/usr/share/doc/ntp-*にドキュメントが存在するので、それをfirefoxなりlynxなり好きなブラウザで。この中のkeygen.htmlに以下のような記述がある。
On each trusted host as root, change to the keys directory. To insure a fresh fileset, remove all ntpkey files. Then run ntp-keygen -T to generate keys and a trusted certificate.
つまりこうだ。信頼の基点(root)として信用されるホストにおいてはそれぞれ、次の三つを実行する。
  1. keysディレクトリに移動する。
  2. ファイル群を新しくするためにntpkeyファイルを削除する。
  3. 公開鍵・秘密鍵ペアと信頼された証明書を生成するため、ntp-keygen -Tコマンドを実行する
そうでないホストについては、どうだろう。
On all other hosts do the same, but leave off the -T flag to generate keys and nontrusted certificates.
つまり、それ以外のホストについては、-Tオプションをつけずに上の手順を実行せよ、ということだ。

ではやってみよう。これまで同様、認証を行わないユニキャストによる時刻同期ができている」ことを前提とする。

サーバ側
次のように実行する。
# cd /etc/ntp
# \rm ntpkey_*
# ntp-keygen -T
Using OpenSSL version 90801f
Random seed file /root/.rnd 1024 bytes
Generating RSA keys (512 bits)...
RSA 0 2 8       1 11 24                         3 1 2
Generating new host file and link
ntpkey_host_ntpserver.localnet->ntpkey_RSAkey_ntpserver.localnet.3382096077
Using host key as sign key
Generating certificate RSA-MD5
X509v3 Basic Constraints: critical,CA:TRUE
X509v3 Key Usage: digitalSignature,keyCertSign
X509v3 Extended Key Usage: trustRoot
Generating new cert file and link
ntpkey_cert_ntpserver.localnet->ntpkey_RSA-MD5cert_ntpserver.localnet.3382096077
#
これで公開鍵・秘密鍵ペアと証明書ができているはずだ。
# ls -lF
total 16
-rw------- 1 root root 266 May 11  2006 keys.orig
lrwxrwxrwx 1 root root  48 Mar  6 00:07 ntpkey_cert_ntpserver.localnet -> ntpkey_RSA-MD5cert_ntpserver.localnet.3382096077
lrwxrwxrwx 1 root root  43 Mar  6 00:07 ntpkey_host_ntpserver.localnet -> ntpkey_RSAkey_ntpserver.localnet.3382096077
-rw-r--r-- 1 root root 629 Mar  6 00:07 ntpkey_RSAkey_ntpserver.localnet.3382096077
-rw-r--r-- 1 root root 620 Mar  6 00:07 ntpkey_RSA-MD5cert_ntpserver.localnet.3382096077
-rw-r--r-- 1 root root 186 Oct 17 20:46 ntpservers
-rw-r--r-- 1 root root   0 May 11  2006 step-tickers
#

続いて、/etc/ntp.confに以下のような行を追加する。
crypto pw ntpserver.localnet randfile /etc/ntp/.rnd
ここで、pwに続くのは、かぎファイルのパスワードで、ntp-keygenコマンドに特別なオプションをつけなければ、gethostname()で得られるホスト名が使用される。これについては、第三回を参照のこと。次のrandfileに続くのは、ランダムシードファイルの場所。ランダムシードファイルの作成についても、前回を参照して欲しい。
最後に、ntpdを再起動する。
# service ntpd restart
Shutting down ntpd:                                        [  OK  ]
Starting ntpd:                                             [  OK  ]
#


クライアント側
まずは、サーバと同様、キーの作成を行う。ただし、-Tオプションを指定しない。
# cd /etc/ntp
# \rm ntpkey_*
# ntp-keygen
Using OpenSSL version 90801f
Random seed file /root/.rnd 1024 bytes
Generating RSA keys (512 bits)...
RSA 0 3 11      1 11 24                         3 1 2
Generating new host file and link
ntpkey_host_ntpclient.localnet->ntpkey_RSAkey_ntpclient.localnet.3382098481
Using host key as sign key
Generating certificate RSA-MD5
X509v3 Basic Constraints: critical,CA:TRUE
X509v3 Key Usage: digitalSignature,keyCertSign
Generating new cert file and link
ntpkey_cert_ntpclient.localnet->ntpkey_RSA-MD5cert_ntpclient.localnet.3382098481
#

次に、/etc/ntp.confを次のように編集する。
server 192.168.55.133 autokey
crypto pw ntpclient.localnet randfile /etc/ntp/.rnd
ここで、192.168.55.133は、NTPサーバのアドレス。後はサーバと同じだ。
ここまでできたら、ntpdを再起動する。
# service ntpd restart
ntpd を停止中:                                             [  OK  ]
ntpd: 時間サーバと同期中:                                  [  OK  ]
ntpd を起動中:                                             [  OK  ]
#


確認
クライアントがサーバと同期したかどうかを確認する。当然、サーバがある時刻ソースに同期した後、さらにしばらくした後でないと確認できない。
# ntpq
ntpq> peers
remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ntpserver.local 208.100.3.151    3 u   23   64  377    0.475  -250717  19.050
LOCAL(0)        LOCAL(0)        10 l   28   64  377    0.000    0.000   0.001
ntpq> associations

ind assID status  conf reach auth condition  last_event cnt
===========================================================
1 52124  f624   yes   yes   ok   sys.peer   reachable  2
2 52125  9024   yes   yes  none    reject   reachable  2
ntpq>


考察
さて、以上でサーバ=クライアント間の時刻同期は成った。だが不可解な点が残る。サーバ=クライアント間で一体何を認証しているのか、ということだ。
X.509公開鍵認証基盤(PKI: Public Key Infrastructure)では、検証者が信頼の基点となる認証局(CA: Certificate Authority)を選び、これらのCAの証明書を予め安全な方法で入手する。検証者は、ある証明書を受け取ったとき、以下の手順でその証明書を検証する。まず、その証明書を発行したCA、そのCAの証明書を発行したCA、…と証明書のパスを辿る。これらの証明書パス中のいずれかの証明書が、信頼の基点となるCAの証明書の集合の内のいずれかと一致すれば、その証明書を信用するに足る、と判断する(というのは乱暴な説明だが、ここはこのくらいで許しといてくれ)
今回の場合、NTPサーバ側もNTPクライアント側も、信頼の基点となる認証局を設定しなかった。とすると本来、どんな証明書を受け取っても、信頼しない、と判断しなければならないはずだ。しかし、実際には「auth: ok」となっている。

サーバ側の鍵および証明書を発行するとき、ntp-keygenコマンドに-Tオプションを付加した。これで何が変わるかというと、証明書中に証明書エクステンション(X509v3 extensions)にcriticalでない拡張鍵用途フィールド(X509v3 Extended Key Usage)が追加され、これに「Trust Root」が指定されていることだけのようだ。実際、-Tオプションをつけずにサーバ側で鍵・証明書を生成すると、クライアント側は時刻同期しないようだ。

以上のことから考えると、現状のntpdでは、サーバ側で-Tを付けているかつけていないかを認証しているに過ぎない。まあ、途中で鍵や証明書が変更されたらそれに気付くのかもしれない(ちゃんとAutokeyのドキュメントを読めば解るのかもしれないが、まだ読めてません…)が、せいぜいその程度だ。実装の問題じゃないかと思うのだが…

ドキュメントkeygen.htmlを読むと次のように書いてある。
As mentioned on the Autonomous Authentication page, the default TC identity scheme is vulnerable to a middleman attack.
もともと脆弱性があるんだから、使うなということだろうか?

第一回:『NTP認証: ユニキャスト・共通鍵認証篇
第二回:『NTP認証: ブロードキャスト・共通鍵認証篇
第三回:『NTP認証: ntp-keygenコマンドとX.509証明書
第四回:『NTP認証: ユニキャスト・公開鍵認証篇
第五回:『NTP認証: マルチキャスト・共通鍵認証篇

2007/02/15

NTP認証: ntp-keygenコマンドとX.509証明書

NTP認証シリーズの第三回。今回は、公開鍵認証に入る前の準備篇。

NTP認証: ユニキャスト・共通鍵認証篇』で既に紹介済みだが、ntpパッケージには、ntp-keygenというコマンドが付属している。このコマンドで、NTPの認証に使用する共通鍵や公開鍵・証明書を生成することができる。基本的な使い方は簡単で、引数なしで起動すれば、公開鍵・証明書を生成してくれる。オプションとして-Mオプションをつければ、共通鍵も生成する。共通鍵ファイルについては、『NTP認証: ユニキャスト・共通鍵認証篇』で述べた通りだ。

では、このコマンドで生成された公開鍵・証明書はどうなっているのか、というのが今回のテーマだ。おさらいとして、公開鍵・証明書を生成するところからやってみよう。
# dd if=/dev/urandom of=/root/.rnd bs=1024 count=1
1+0 records in
1+0 records out
1024 bytes (1.0 kB) copied, 0.240445 seconds, 4.3 kB/s
# ntp-keygen
Using OpenSSL version 90801f
Random seed file /root/.rnd 1024 bytes
Generating RSA keys (512 bits)...
RSA 0 40 46     1 11 24                         3 1 2
Generating new host file and link
ntpkey_host_ホスト名->ntpkey_RSAkey_ホスト名.3380508833
Using host key as sign key
Generating certificate RSA-MD5
X509v3 Basic Constraints: critical,CA:TRUE
X509v3 Key Usage: digitalSignature,keyCertSign
Generating new cert file and link
ntpkey_cert_ホスト名->ntpkey_RSA-MD5cert_ホスト名.3380508833
#
最初のddコマンドは、ntp-keygenコマンド実行前に/root/.rndがない場合、エラーになるのを避けるためだ。

メッセージを見ると、RSA 512bitの鍵を生成してる。今時512bitでもなかろうに、とも思わなくもないが、NTPプロトコル上の制限なのか…。

実際に生成されたファイルを確かめてみよう。
# cd /etc/ntp
# ls -F
keys
ntpkey_RSA-MD5cert_ホスト名.3380508833
ntpkey_RSAkey_ホスト名.3380508833
ntpkey_cert_ホスト名@
ntpkey_host_ホスト名@
ntpservers
step-tickers
# cat ntpkey_RSAkey_ホスト名.3380508833
# ntpkey_RSAkey_ホスト名.3380508833
# Thu Feb 15 15:13:53 2007
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-CBC,389C92663ECF5DB9

wrSy9Q++1KwQ13Day9uY8TlvpYweLEjHmLtd0YiJFFvdNahQMRru4Zc+YL+o4VZk
<<略>>
RiARMG0NVXvkBwpVIIykS5GhGVEjqbT9+ckvZ8C0q3E=
-----END RSA PRIVATE KEY-----
#
むむ?パスワードを指定した覚えはないが…ソースコードを当たってみると、-p パスワードオプションが指定されなかった場合は、gethostname()で得られるホスト名が使われるようだ。実際にそうなっているか、openssl rsaコマンドを使って確認してみよう。
# openssl rsa -text -noout < ホスト名.3380508833
Enter pass phrase: ← ホスト名を入力
Private-Key: (512 bit)
modulus:
00:e2:7c:35:92:2a:de:15:18:1d:98:97:9c:5f:74:
f6:4f:9b:e9:c7:0a:4a:db:2e:15:fc:6c:00:f6:8c:
<<略>>
06:7b
#
確かにRSA 512bitになっている。

証明書を確認してみよう。
# cat ntpkey_RSA-MD5cert_ホスト名.3380508833
# ntpkey_RSA-MD5cert_ホスト名.3380508833
# Thu Feb 15 15:13:53 2007
-----BEGIN CERTIFICATE-----
MIIBSzCB9qADAgECAgTJfnihMA0GCSqGSIb3DQEBBAUAMB0xGzAZBgNVBAMTEmlu
YXp1bWEuZGVzdHJveWVyczAeFw0wNzAyMTUwNjEzNTNaFw0wODAyMTUwNjEzNTNa
MB0xGzAZBgNVBAMTEmluYXp1bWEuZGVzdHJveWVyczBaMA0GCSqGSIb3DQEBAQUA
A0kAMEYCQQDifDWSKt4VGB2Yl5xfdPZPm+nHCkrbLhX8bAD2jP//XaEh9g11C++l
/xPXAxA4Q+88ehQq840V2wgq8o6pgznbAgEDoyAwHjAPBgNVHRMBAf8EBTADAQH/
MAsGA1UdDwQEAwIChDANBgkqhkiG9w0BAQQFAANBANaYyZ0ZUCd+fYt9DbuNMmVb
T/pcR2rD2s7QuI2tJVa3ebmal/dz3nAPlfEadm35pQSAmjIpB0ebbOef1+EcqSA=
-----END CERTIFICATE-----
# openssl x509 -text -noout -in ntpkey_RSA-MD5cert_ホスト名.3380508833
Certificate:
Data:
Version: 3 (0x2)
Serial Number: -914458463 (-0x3681875f)
Signature Algorithm: md5WithRSAEncryption
Issuer: CN=ホスト名
Validity
Not Before: Feb 15 06:13:53 2007 GMT
Not After : Feb 15 06:13:53 2008 GMT
Subject: CN=ホスト名
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (512 bit)
Modulus (512 bit):
00:e2:7c:35:92:2a:de:15:18:1d:98:97:9c:5f:74:
f6:4f:9b:e9:c7:0a:4a:db:2e:15:fc:6c:00:f6:8c:
ff:ff:5d:a1:21:f6:0d:75:0b:ef:a5:ff:13:d7:03:
10:38:43:ef:3c:7a:14:2a:f3:8d:15:db:08:2a:f2:
8e:a9:83:39:db
Exponent: 3 (0x3)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage:
Digital Signature, Certificate Sign
Signature Algorithm: md5WithRSAEncryption
d6:98:c9:9d:19:50:27:7e:7d:8b:7d:0d:bb:8d:32:65:5b:4f:
fa:5c:47:6a:c3:da:ce:d0:b8:8d:ad:25:56:b7:79:b9:9a:97:
f7:73:de:70:0f:95:f1:1a:76:6d:f9:a5:04:80:9a:32:29:07:
47:9b:6c:e7:9f:d7:e1:1c:a9:20
#
極々シンプルな自己署名証明書になっている。有効期限は一年間だ。シリアル番号がランダマイズされているのは偉い…のか、管理するのが面倒だったからなのか(笑)。仕様的には問題ないはずだが、負のシリアル番号は初めて見た。

自己署名なので、当然IssuerとSubjectが同一になっている。マニュアルによれば、これはそれぞれ、-s-iオプションで変更できることになっている。

-i name
Set the suject name to name. This is used as the subject field in certificates and in the file name for host and sign keys.
-s name
Set the issuer name to name. This is used for the issuer field in certificates and in the file name for identity files.
しかし、オプションの名前から考えて、これは逆なんじゃなかろうか?実際に確かめてみよう。
# rm *.3380508833
rm: remove 通常ファイル `ntpkey_RSA-MD5cert_ホスト名.3380508833'? y
rm: remove 通常ファイル `ntpkey_RSAkey_ホスト名.3380508833'? y
# ntp-keygen -i "subject.localnet" -s "issuer.localnet"
Using OpenSSL version 90801f
Random seed file /root/.rnd 1024 bytes
Generating RSA keys (512 bits)...
RSA 0 12 19     1 11 24                         3 1 2
Generating new host file and link
ntpkey_host_issuer.localnet->ntpkey_RSAkey_issuer.localnet.3380513148
Using host key as sign key
Generating certificate RSA-MD5
X509v3 Basic Constraints: critical,CA:TRUE
X509v3 Key Usage: digitalSignature,keyCertSign
Generating new cert file and link
ntpkey_cert_issuer.localnet->ntpkey_RSA-MD5cert_issuer.localnet.3380513148
# ls
keys                                           ntpkey_host_ホスト名
ntpkey_RSA-MD5cert_issuer.localnet.3380513148  ntpkey_host_issuer.localnet
ntpkey_RSAkey_issuer.localnet.3380513148       ntpservers
ntpkey_cert_ホスト名                 step-tickers
ntpkey_cert_issuer.localnet
# openssl x509 -text -noout -in ntpkey_RSA-MD5cert_issuer.localnet.3380513148
Certificate:
Data:
Version: 3 (0x2)
Serial Number: -914454148 (-0x36817684)
Signature Algorithm: md5WithRSAEncryption
Issuer: CN=subject.localnet
Validity
Not Before: Feb 15 07:25:48 2007 GMT
Not After : Feb 15 07:25:48 2008 GMT
Subject: CN=issuer.localnet
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (512 bit)
Modulus (512 bit):
00:c5:c8:2d:6a:95:05:1e:7f:76:b3:7e:7a:f7:5b:
85:ff:00:76:b1:fe:32:62:d4:fe:41:9a:da:05:2f:
04:0f:f9:0b:97:b7:b7:0b:90:72:ba:9e:42:de:0a:
d5:d8:3d:83:c2:e3:7d:b0:84:a4:56:ac:bf:f5:f0:
c3:9e:6a:2e:11
Exponent: 3 (0x3)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage:
Digital Signature, Certificate Sign
Signature Algorithm: md5WithRSAEncryption
16:a5:2b:bb:19:8e:79:e2:08:6d:f8:76:ed:99:db:f8:ed:22:
46:af:90:67:62:c5:cb:09:c7:03:e8:ea:1f:21:c0:90:3d:08:
db:60:69:7c:e6:8e:47:5b:6a:9f:e9:e0:96:04:f7:a8:e7:d5:
08:eb:c3:53:67:6f:29:7f:40:9d
#
思った通り逆になっている。ファイル名はどうなるのかと思ったら、すべてに対して-sで指定したもの(issuer.localnet)が使われている。まあ、Issuerと言えば認証局(Certificate Authority, CA)のことで、CAは複数subjectに対して複数の証明書を発行するということを考えれば、ファイル名にIssuerの名前でなく、Subjectの名前が使われるのが自然だろう。そうでなければ、証明書のファイル名が衝突してしまうからだ。

しかし、自己署名証明書のIssuerとSubjectが違うってのはどうだろう(笑)?

第一回:『NTP認証: ユニキャスト・共通鍵認証篇
第二回:『NTP認証: ブロードキャスト・共通鍵認証篇
第三回:『NTP認証: ntp-keygenコマンドとX.509証明書
第四回:『NTP認証: ユニキャスト・公開鍵認証篇
第五回:『NTP認証: マルチキャスト・共通鍵認証篇