暗号、SSL、SSH

分散システム

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2005/2006-02-28
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/

■連絡事項

3月7日(火)は、試験をやります。資料持ち込み可能です。

■参考文献

■暗号

◆暗号に関する基本用語と安全性

暗号とは、情報の意味が当事者以外にはわからないように情報を変 換することである。

図? 暗号の考え方

図? 暗号の考え方

平文(ひらぶん(clear text))
元の情報
暗号文(cipher text)
変換された情報
平文、暗号文といっても、文字だけでなく、画像や音声などコンピュータが扱 えるあらゆるデータが想定されている。

暗号化(encrypt)
平文を暗号文に変換すること。暗号化鍵が必要。
復号化(decrypt)
暗号文を平文にもどすこと。復号化鍵が必要。
鍵(key)
暗号化や複合化に必要な(短い)データ。
解読
当事者以外の第三者が、暗号文を元にもどすこと、あるいは、復号化鍵を得る こと。
暗号化や複合化の方法(アルゴリズム)は、何種類もある。

◆鍵を使うことの重要性

問: 答え:

暗号化の方法が秘密になっていると、一見、より強そうにみえる。しかし、そ の暗号が、強いのか弱いのか調べる方法がない。攻撃すると、簡単に落ちるか もしれない。暗号化の方法を提供している者が信頼できない時には使えない。

◆長い鍵を使うことの重要性

暗号の安全性は、鍵の安全性によっている。

◆暗号の経済学

暗号の安全は、解読にかかるコストを大きくすることで、解読され た平文から得られる利益を相対的に小さくすることに依存している。

鍵を長くするだけで、安全性が指数関数的に高くなる。 鍵を1ビット長くすると、解読時間が2倍になる。 (「鍵の長さを2倍にすると解読時間が2倍になる」は、誤り)。

図? 指数関数

図? 指数関数

図? 指数関数

図? 指数関数

パスワードは、コンピュータの中では、暗号化の鍵として使われる。 長いパスワードは、破られにくい。1文字(大文字小文字数字記号)増やすと、 総当たりで解読に要する時間が、50倍から100倍近くかかるようになる。

◆共通鍵暗号系と公開鍵暗号系

暗号の方法は、大きく2つに分類される

共通鍵暗号系(対称暗号系)
暗号化鍵と復号化鍵が同じ(または片方から片方が簡単に計算できる)。
公開鍵暗号系(非対称暗号系)
暗号化鍵から復号化鍵を容易に類推できない。

DES は、Unix のパスワードのハッシュ関数として使われている。

◆AES

Advanced Encryption Standard。

アメリカ NIST (National Institute of Standards and Technology) が 定めたDES に変わる新しい標準。 全世界に対して公募され、ベルギーのJoan Daemen とVincent Rijmenにより開発されたRijndael方式が採用された。鍵の長さは、 128ビット、192ビット、256ビットから選べる。

◆一方向関数

y=f(x) で、x から y を計算することは簡単だが、y から x 逆を計算するこ とは非常に難しい関数。

◆ハッシュ関数(メッセージ・ダイジェスト)

元データからデータの指紋と呼ぶべきような特徴的な数(普通は元データの長 さによらず固定長)を抽出するもの。

チェックサムや CRC (Cyclic Redundancy Check) にも似ているが、暗号やディ ジタル署名で使われるのは、Collision Proof 性が求められる。

◆暗号によるハッシュ関数の実現

暗号を使えば、一方向関数が作れる(暗号を使わなくても一方向関数を作るこ とはできる)。

one_way_function( x )
{
	return x をキーとして 0 を暗号化したもの ;
}
Unix の /etc/passwd や Apache の htpasswd で遣われているものは、DES を25回繰り返して使って 作ったハッシュ関数の結果。パスワードそのものは、保存されてない。

◆MD2、MD4、MD5

RSA社の B.Kaliski や R.Rivest らによって提案されたメッセージ・ダイジェ ストのアルゴリズム。任意の長さのデータから128ビットのメッセージ・ダイ ジェストを生成する。

◆SHA1 (Secure Hash Algorithm 1)

アメリカの NIST(National Institute of Standards and Technology) が 定めた標準的なメッセージ・ダイジェスト。 出力は、160 ビット。

◆公開鍵暗号系

公開鍵暗号系(非対称暗号系)では2つの異なる鍵を用いる。 便宜上、この2つを公開鍵と秘密鍵と呼ぶ。

これらの鍵は、互いに相手の逆関数になっている。

図? 公開鍵暗号を使った暗号通信の手順

図? 公開鍵暗号を使った暗号通信の手順

  1. 受手は、公開鍵と秘密鍵の組を作り、公開鍵を誰でも読めるようにする。
  2. 送手は、受手の公開鍵を暗号化鍵として用いて暗号文を作り、送る。
  3. 送手は、受け取った暗号文を、自分の秘密鍵を復号化鍵として用いて復号化し、 元の平文を得る。

ここで、公開鍵から秘密鍵を計算することは難しい。ある平文を公開鍵で暗号 化してみたところで、秘密鍵を得ることは難しい。

公開鍵暗号の利点は、鍵を管理する手間が掛らないこと。

共通鍵暗号
情報を交換する間で鍵を安全に共有しなければならない。しかも、通信 相手ごとに鍵を変える必要がある。
公開鍵暗号
受手ごとに、1つの暗号化鍵を公開するだけでよい。今までに通信をしたこと がない人からでも、暗号化されたメッセージを受け取ることが可能である。
公開鍵暗号系は、暗号通信だけでなくディジタル署名や利用者認証、電子現金 にも応用される。

◆RSA

Rivest Shamir Adleman。

RSA暗号は、Rivest, Shamir, Adleman の3人によって開発され た公開鍵暗号系である。RSA暗号の安全性は、大きな数を素因数 分解することの難しさに基づく。北米では、RSAは、2000年 に特許が切れた。

◆楕円曲線暗号

Elliptic Curve Cryptosystem。

公開鍵に基づく暗号化の1つの方法。買得の難しさは、楕円曲線上の離散対数 問題を解くのと同程度と言われている。RSA よりも鍵が短くて高速である。

2002年9月、Sun がソース・コードを OpenSSL プロジェクトに寄進した。

◆認証

認証とは、情報の正当性や完全性を確保する技術である。

利用者認証
アクセスしてきた人が正当か否かを判定する。 しばしばパスワードや暗唱番号が用いられる。
ディジタル署名(メッセージ認証、電子署名)
通常の署名とおなじく、送られてきたメッセージが送信者本人のもので あることを識別、確認すること。

◆認証の例

◆ディジタル署名

ディジタル署名では、通常の署名と同様に、次のような性質が必要である。

ディジタル・データでは完全なコピーが簡単に作れるので、紙上の署名や捺印 よりも難しい。

公開鍵暗号系を使ってディジタル署名を行うことができる。

図? 公開鍵暗号を使ったディジタル署名の手順

図? 公開鍵暗号を使ったディジタル署名の手順

  1. (受手ではなく)送手は、公開鍵と秘密鍵の組を作り、公開鍵を誰でも 読めるようにする。
  2. 送手は、自分の秘密鍵を暗号化鍵として用いて暗号文を作り、送る。
  3. 送手は、受け取った暗号文を、送手の秘密鍵を復号化鍵として用いて復 号化し、元の平文を得る。この時、きちんと平文が得られた場合、その平文は、 その公開鍵の持ち主から送られてきたことがわかる。

メッセージ全体を暗号化する代わりに、メッセージを平文で送り、それにメッ セージを一方向関数(ハッシュ関数)と呼ばれる方法で計算した結果だけを、 秘密鍵で暗号化したものを送る方法もある。一方向関数では、計算結果から元 の値(メッセージ)を計算することが難しい。

ディジタル署名や利用者認証は、公開鍵暗号系ではなく、共通鍵暗号系を用い ても可能である。ただし、この場合、鍵を管理する信用できる管理センターが 必要となる。

◆公開鍵暗号を使った利用者認証

サーバへのログインを例に、これを説明する。

  1. ユーザは、サーバにログイン・アカウントを登録する時に、公開鍵と秘 密鍵を生成し、公開鍵をサーバに届け、秘密鍵を自分で保持する。
  2. ユーザは、通信回線を通じてサーバにアクセスしてきた時、サーバは乱 数を1つ生成し、その乱数をユーザの「公開鍵」で暗号化し、ユーザに送り返 す。
  3. ユーザは、送られてきた暗号化された乱数を、保持している秘密鍵で復 号化し、サーバに送り返す。
  4. サーバは、ユーザから返された乱数が正しければ、正当なユーザである と判定する。
次回の呼び出しでは、別の乱数を用いることで、通信を記録している傍受者に も対応することができる(challenge-response方式)。

単なる暗証番号の場合、通信を傍受されたら終り。 毎回違う数を使えば、傍受されていても平気。

◆鍵の確認

公開鍵で自由に鍵が得られたとしても、鍵か偽物だと、意味はない。

鍵がが本物であるかをどうやって確認するか。

では、その第三者は、信頼できるのか。

■SSL(Secure Sockets Layer)

SSL は、Netscape 社によって開発された通信路を暗号化する仕組み。 認証機能もある。 HTTP に広く使われている(他にも使える)。 SSL を IETF により標準化したものが、TLS(Transport Layer Security).

◆3種類認証モデル

良く使われるのは、2番目。 Twins の初期の問題。オレオレ証明書を提示していた。

認証には、証明書が使われる。 鍵の交換には、証明書に含まれている

◆man-in-the-middle攻撃

A=攻撃者、攻撃者=Bで暗号通信

図? man-in-the-middle攻撃

◆証明書

X.509 形式(バイナリ)を、テキストに変換したものの例:

% openssl x509 -text -noout < www3.cert[←]
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            e0:bf:cf:45:14:b3:d7:41:6c:2b:3d:42:f0:99:58:88
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=GB, O=Comodo Limited, OU=Comodo Trust Network, OU=Terms and Conditions of use: http://www.comodo.net/repository, OU=(c)2002 Comodo Limited, CN=Comodo Class 3 Security Services CA
        Validity
            Not Before: Nov 14 00:00:00 2005 GMT
            Not After : Nov 22 23:59:59 2006 GMT
        Subject: C=JP/2.5.4.17=305-8573, ST=Ibaraki, L=Tsukuba/2.5.4.9=1-1-1,Tennohdai, O=University of Tsukuba, OU=College of Information Sciences, OU=Provided by Toriton,Inc., OU=Toriton,Inc SSL, CN=www3.coins.tsukuba.ac.jp
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:ba:be:80:00:09:40:af:96:5a:81:60:5c:9a:b2:
                    5d:7b:1a:79:99:e7:bf:4f:d8:6c:1b:99:f5:3c:3d:
                    6e:f6:0d:1d:a0:b0:8d:fd:db:52:7c:dd:b2:d8:5d:
                    aa:44:c8:4b:ec:2f:56:81:ce:14:1d:39:a2:fc:87:
                    f3:29:64:1c:6b:85:29:fe:6c:8e:8e:4f:b2:84:8c:
                    4b:ea:66:02:56:6a:3d:34:20:8a:09:c1:bb:6b:f6:
                    4c:da:87:99:d3:bd:b6:42:6e:c6:82:c0:2d:ca:a1:
                    b1:35:ff:ce:e3:00:8e:e7:0d:8e:ec:9b:2b:12:ea:
                    9e:07:de:ce:0a:30:11:4d:9b
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier: 
                keyid:36:E0:E8:7C:6D:9D:45:91:EE:99:E5:42:76:4D:70:B3:50:30:AC:5E

            X509v3 Subject Key Identifier: 
                CF:BC:0C:F1:D3:57:40:DB:74:08:81:4C:81:92:A0:A8:D1:50:7C:D8
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication, TLS Web Client Authentication
            Netscape Cert Type: 
                SSL Client, SSL Server
            X509v3 Certificate Policies: 
                Policy: 1.3.6.1.4.1.6449.1.2.1.3.4
                  CPS: https://secure.comodo.net/CPS

            X509v3 CRL Distribution Points: 
                URI:http://crl.comodo.net/Class3SecurityServices_3.crl
                URI:http://crl.comodoca.com/Class3SecurityServices_3.crl
                email:Class3SecurityServices_3@crl.comodo.net

    Signature Algorithm: sha1WithRSAEncryption
        bc:57:a5:fb:9c:07:77:90:bd:21:93:20:48:23:99:22:74:c9:
        66:19:5d:06:d1:e2:a9:ae:24:de:e9:ab:b8:e1:cd:38:59:5a:
        8f:67:47:ed:7a:a7:8c:e6:78:b1:5c:bf:be:0f:cf:98:53:38:
        82:66:67:82:d3:1c:5f:6d:1a:1f:ea:96:92:0b:d4:74:fc:7a:
        9b:21:b6:72:0f:5d:67:38:ac:2b:de:2d:6a:6c:a4:b4:74:43:
        64:38:5e:c5:3f:55:07:30:91:47:21:cd:ed:f1:5f:5c:ee:a3:
        fa:66:5e:8c:98:07:b2:67:32:1b:7a:bd:41:da:41:67:34:88:
        53:7c:c3:f3:f0:e3:23:cc:37:94:e8:e4:4f:25:f3:6c:c3:7c:
        92:65:64:28:de:e2:0d:3e:e0:82:38:31:25:90:0a:33:e9:20:
        54:f6:a4:bc:43:f5:69:55:65:d9:2b:47:8e:7d:e7:39:75:25:
        7b:b9:a4:cc:ff:6e:5c:09:f0:d7:e4:01:e5:5c:bc:0b:2c:d2:
        26:bf:17:b5:14:80:62:1f:4d:c5:30:81:db:28:da:e3:dc:0b:
        6a:c1:73:38:22:15:b7:99:9b:e7:30:64:85:40:be:d3:d4:a9:
        d4:2c:4e:37:90:64:d4:13:06:9d:98:83:d2:d4:f8:ff:b4:79:
        45:6e:4b:aa
% []

◆認証局の階層

証明書がついていたとして、それが本物であるかをどうやって確認するか。

認証局(CA, Certificate Authority)に、証明書を発行してもらう。(認証局の 秘密鍵でディジタル署名をしてもらう)

その認証局は、信頼できるか?

WWWブラウザには、ルート認証局の証明書が予め含まれている。

末端のWWWサイトは、ルート認証局、または、中間認証局から発行された証 明書を提示する。

◆ハンドシェーク

接続時に、乱数(共通鍵暗号に基づく暗号化の鍵を生成するため)を交換する。 その乱数は、普通、サーバ側が提示した証明書に含まれている公開鍵で暗号化 される。

ハンドシェークで使われる公開鍵暗号系

データを暗号化するために使われる共通鍵暗号系

◆openssl コマンドによる SSL 付き Apache との対話

WWW ページ https://www3.coins.tsukuba.ac.jp/~yas/ を、openssl コマンドを使って得る。
% openssl s_client -connect www3.coins.tsukuba.ac.jp:https -state[←]
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=1 /C=GB/O=Comodo Limited/OU=Comodo Trust Network/OU=Terms and Conditions of use: http://www.comodo.net/repository/OU=(c)2002 Comodo Limited/CN=Comodo Class 3 Security Services CA
verify error:num=20:unable to get local issuer certificate
verify return:0
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A
---
Certificate chain
 0 s:/C=JP/2.5.4.17=305-8573/ST=Ibaraki/L=Tsukuba/2.5.4.9=1-1-1,Tennohdai/O=University of Tsukuba/OU=College of Information Sciences/OU=Provided by Toriton,Inc./OU=Toriton,Inc SSL/CN=www3.coins.tsukuba.ac.jp
   i:/C=GB/O=Comodo Limited/OU=Comodo Trust Network/OU=Terms and Conditions of use: http://www.comodo.net/repository/OU=(c)2002 Comodo Limited/CN=Comodo Class 3 Security Services CA
 1 s:/C=GB/O=Comodo Limited/OU=Comodo Trust Network/OU=Terms and Conditions of use: http://www.comodo.net/repository/OU=(c)2002 Comodo Limited/CN=Comodo Class 3 Security Services CA
   i:/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Global Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFfzCCBGegAwIBAgIRAOC/z0UUs9dBbCs9QvCZWIgwDQYJKoZIhvcNAQEFBQAw
gdwxCzAJBgNVBAYTAkdCMRcwFQYDVQQKEw5Db21vZG8gTGltaXRlZDEdMBsGA1UE
CxMUQ29tb2RvIFRydXN0IE5ldHdvcmsxRjBEBgNVBAsTPVRlcm1zIGFuZCBDb25k
aXRpb25zIG9mIHVzZTogaHR0cDovL3d3dy5jb21vZG8ubmV0L3JlcG9zaXRvcnkx
HzAdBgNVBAsTFihjKTIwMDIgQ29tb2RvIExpbWl0ZWQxLDAqBgNVBAMTI0NvbW9k
byBDbGFzcyAzIFNlY3VyaXR5IFNlcnZpY2VzIENBMB4XDTA1MTExNDAwMDAwMFoX
DTA2MTEyMjIzNTk1OVowggEIMQswCQYDVQQGEwJKUDERMA8GA1UEERMIMzA1LTg1
NzMxEDAOBgNVBAgTB0liYXJha2kxEDAOBgNVBAcTB1RzdWt1YmExGDAWBgNVBAkT
DzEtMS0xLFRlbm5vaGRhaTEeMBwGA1UEChMVVW5pdmVyc2l0eSBvZiBUc3VrdWJh
MSgwJgYDVQQLEx9Db2xsZWdlIG9mIEluZm9ybWF0aW9uIFNjaWVuY2VzMSEwHwYD
VQQLExhQcm92aWRlZCBieSBUb3JpdG9uLEluYy4xGDAWBgNVBAsTD1Rvcml0b24s
SW5jIFNTTDEhMB8GA1UEAxMYd3d3My5jb2lucy50c3VrdWJhLmFjLmpwMIGfMA0G
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6voAACUCvllqBYFyasl17GnmZ579P2Gwb
mfU8PW72DR2gsI3921J83bLYXapEyEvsL1aBzhQdOaL8h/MpZBxrhSn+bI6OT7KE
jEvqZgJWaj00IIoJwbtr9kzah5nTvbZCbsaCwC3KobE1/87jAI7nDY7smysS6p4H
3s4KMBFNmwIDAQABo4IBjzCCAYswHwYDVR0jBBgwFoAUNuDofG2dRZHumeVCdk1w
s1AwrF4wHQYDVR0OBBYEFM+8DPHTV0DbdAiBTIGSoKjRUHzYMA4GA1UdDwEB/wQE
AwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
AjARBglghkgBhvhCAQEEBAMCBsAwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwQw
KzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwgbAG
A1UdHwSBqDCBpTA4oDagNIYyaHR0cDovL2NybC5jb21vZG8ubmV0L0NsYXNzM1Nl
Y3VyaXR5U2VydmljZXNfMy5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwuY29tb2RvY2Eu
Y29tL0NsYXNzM1NlY3VyaXR5U2VydmljZXNfMy5jcmwwLaAroCmBJ0NsYXNzM1Nl
Y3VyaXR5U2VydmljZXNfM0BjcmwuY29tb2RvLm5ldDANBgkqhkiG9w0BAQUFAAOC
AQEAvFel+5wHd5C9IZMgSCOZInTJZhldBtHiqa4k3umruOHNOFlaj2dH7XqnjOZ4
sVy/vg/PmFM4gmZngtMcX20aH+qWkgvUdPx6myG2cg9dZzisK94tamyktHRDZDhe
xT9VBzCRRyHN7fFfXO6j+mZejJgHsmcyG3q9QdpBZzSIU3zD8/DjI8w3lOjkTyXz
bMN8kmVkKN7iDT7ggjgxJZAKM+kgVPakvEP1aVVl2StHjn3nOXUle7mkzP9uXAnw
1+QB5Vy8CyzSJr8XtRSAYh9NxTCB2yja49wLasFzOCIVt5mb5zBkhUC+09Sp1CxO
N5Bk1BMGnZiD0tT4/7R5RW5Lqg==
-----END CERTIFICATE-----
subject=/C=JP/2.5.4.17=305-8573/ST=Ibaraki/L=Tsukuba/2.5.4.9=1-1-1,Tennohdai/O=University of Tsukuba/OU=College of Information Sciences/OU=Provided by Toriton,Inc./OU=Toriton,Inc SSL/CN=www3.coins.tsukuba.ac.jp
issuer=/C=GB/O=Comodo Limited/OU=Comodo Trust Network/OU=Terms and Conditions of use: http://www.comodo.net/repository/OU=(c)2002 Comodo Limited/CN=Comodo Class 3 Security Services CA
---
No client certificate CA names sent
---
SSL handshake has read 3296 bytes and written 314 bytes
---
New, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
Server public key is 1024 bit
SSL-Session:
    Protocol  : TLSv1
    Cipher    : EDH-RSA-DES-CBC3-SHA
    Session-ID: BF27EB1F384AA023B6929C4B7CBE4C013E97B9FC5410A3115D99A9FD021556F5
    Session-ID-ctx: 
    Master-Key: 8F7FDFF39481E80B0FD033BF6E72A51CA756C6CF9985AAEF77E41446DC87773062DEA5C24F331F8AD65CA2DCB48E11A7
    Key-Arg   : None
    Start Time: 1140864729
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
GET /~yas/ HTTP/1.0[←]
[←]
HTTP/1.1 200 OK
Date: Sat, 25 Feb 2006 10:52:21 GMT
Server: Apache/1.3.27 (Unix)  (Red-Hat/Linux) mod_ssl/2.8.12 OpenSSL/0.9.6 DAV/1.0.2 PHP/4.1.2 mod_perl/1.24_01 mod_throttle/3.1.2
Last-Modified: Mon, 17 Jan 2005 04:21:48 GMT
ETag: "6ef4445-1e8-41eb3d5c"
Accept-Ranges: bytes
Content-Length: 488
Connection: close
Content-Type: text/html

<HTML>
<HEAD>
<TITLE> SHINJO,Yasushi / Secure WWW
</TITLE>
</HEAD>

<BODY>

<H1>内容</H1>

<UL>
<LI> <A HREF="coins-admin/2003/d/tiki.cgi">coins-admin 用 Tiki (2003)</A>
<LI> <A HREF="j03/d/tiki.cgi">情報学類2003年度入学生のための Tiki (2003)</A>
</UL>

<HR>
 <BR>
<ADDRESS> <A HREF="http://www.is.tsukuba.ac.jp/~yas/">Yasushi Shinjo</A> / &lt;yas@is.tsukuba.ac.jp&gt; </ADDRESS>
</BODY>
</HTML>

SSL3 alert read:warning:close notify
closed
SSL3 alert write:warning:close notify
% []

◆SSLの実装

OpenSSL は、SSL 以外の暗合のプログラムも含んでいる。

◆プログラミング(in Java)

Socket, ServerSocket の代りに SSLSocket, SSLServerSocket を使う。 keytool で秘密鍵と証明書を作り、鍵置き場に保存する(CAなしでやる時)。

◆クライアント

   1:	
   2:	/*
   3:	        SSLEchoClient.java -- 文字列を送受信するクライアント(SSL版)
   4:	        ~yas/syspro/ipc/SSLEchoClient.java
   5:	        Created on 2004/02/14 21:09:17
   6:	*/
   7:	
   8:	import java.net.*;
   9:	import java.io.*;
  10:	import javax.net.*;
  11:	import javax.net.ssl.*;
  12:	
  13:	class SSLEchoClient
  14:	{
  15:	    public static void main(String argv[]) throws IOException {
  16:	        if( argv.length != 2 )
  17:	        {
  18:	            System.err.println("Usage: % java SSLEchoClient host port");
  19:	            System.exit( -1 );
  20:	        }
  21:	        String server = argv[0];
  22:	        int portno = Integer.parseInt( argv[1] );
  23:	        echo_client( server, portno );
  24:	    }
  25:	    public static void echo_client( String server, int portno )
  26:	        throws IOException
  27:	    {
  28:	        Socket sock = makeSSLClientSocket( server, portno );
  29:	        BufferedReader in = new BufferedReader(
  30:	            new InputStreamReader( sock.getInputStream() ));
  31:	        PrintStream out = new PrintStream( sock.getOutputStream() );
  32:	        stdout.print("==> ");
  33:	        String sline;
  34:	        while( (sline = stdin.readLine())!= null )
  35:	        {
  36:	            stdout.println("sending: ["+sline +"]");
  37:	            out.println( sline );
  38:	            String rline = in.readLine();
  39:	            stdout.println("received: ["+rline+"]");
  40:	            stdout.print("==> ");
  41:	        }
  42:	        stdout.println("");
  43:	        in.close();
  44:	        out.close();
  45:	        sock.close();
  46:	    }
  47:	    static SSLSocket makeSSLClientSocket( String server, int portno )
  48:	        throws java.io.IOException
  49:	    {
  50:	        SSLSocket ss;
  51:	        SSLSocketFactory ssf = (SSLSocketFactory)SSLSocketFactory.getDefault();
  52:	        Socket s = new Socket( server, portno );
  53:	        ss = (SSLSocket) ssf.createSocket(s,server,portno,true);
  54:	        return( ss );
  55:	    }
  56:	    static java.io.BufferedReader stdin = 
  57:	        new java.io.BufferedReader( new java.io.InputStreamReader(System.in) );
  58:	    static java.io.PrintStream stdout = System.out;
  59:	    static java.io.PrintStream stderr = System.err;     
  60:	}
通常の Socket 版と違う所は、makeSSLClientSocket() だけ。
% diff  EchoClient.java SSLEchoClient.java [←]
3,4c3,4
<       EchoClient.java -- 文字列を送受信するクライアント(TCP/IP版)
<       ~yas/syspro/ipc/EchoClient.java
---
>       SSLEchoClient.java -- 文字列を送受信するクライアント(SSL版)
>       ~yas/syspro/ipc/SSLEchoClient.java
9a10,11
> import javax.net.*;
> import javax.net.ssl.*;
11c13
< class EchoClient
---
> class SSLEchoClient
16c18
<           System.err.println("Usage: % java EchoClient host port");
---
>           System.err.println("Usage: % java SSLEchoClient host port");
23d24
< 
27c28
<       Socket sock = new Socket( server, portno );
---
>       Socket sock = makeSSLClientSocket( server, portno );
45a47,55
>     static SSLSocket makeSSLClientSocket( String server, int portno )
>       throws java.io.IOException
>     {
>       SSLSocket ss;
>       SSLSocketFactory ssf = (SSLSocketFactory)SSLSocketFactory.getDefault();
>       Socket s = new Socket( server, portno );
>       ss = (SSLSocket) ssf.createSocket(s,server,portno,true);
>       return( ss );
>     }
50d59
< 
% []

◆サーバ(Java)

   1:	/*
   2:	        SSLEchoServer.java -- 文字列を送受信するサーバ(SSL版)
   3:	        ~yas/syspro/ipc/SSLEchoServer.java
   4:	        Created on 2004/02/14 16:22:13
   5:	*/
   6:	
   7:	import java.net.*;
   8:	import java.io.*;
   9:	import javax.net.ssl.*;
  10:	
  11:	class SSLEchoServer
  12:	{
  13:	    public static void main(String argv[]) throws IOException {
  14:	        if( argv.length != 1 )
  15:	        {
  16:	            System.err.println("Usage: % java SSLEchoServer port");
  17:	            System.exit( -1 );
  18:	        }
  19:	        int portno = Integer.parseInt( argv[0] );
  20:	        echo_server( portno );
  21:	    }
  22:	
  23:	    public static void echo_server( int portno ) throws IOException
  24:	    {
  25:	        ServerSocket acc = makeSSLServerSocket( portno );
  26:	        print_my_host_port( portno );
  27:	        while( true )
  28:	        {
  29:	            Socket com = acc.accept();
  30:	            tcp_peeraddr_print( com );
  31:	            Thread th = new Thread( new EchoServerWorker(com) );
  32:	            th.start();
  33:	        }
  34:	    }
  35:	    public static void print_my_host_port( int portno ) throws UnknownHostException
  36:	    {
  37:	        InetAddress ia = java.net.InetAddress.getLocalHost();
  38:	        String hostname = ia.getHostName();
  39:	        stdout.println("run openssl s_client -host "+hostname+" -port "+portno );
  40:	    }
  41:	    public static void tcp_peeraddr_print( Socket com )
  42:	    {
  43:	        InetSocketAddress isa = (InetSocketAddress)com.getRemoteSocketAddress();
  44:	        InetAddress ia = isa.getAddress();
  45:	        String peerhostaddr = ia.getHostAddress();
  46:	        int peerportno = isa.getPort();
  47:	        stdout.println("connection (hash=="+com.hashCode()+") from "+peerhostaddr+":"+peerportno );
  48:	    }
  49:	    static SSLServerSocket makeSSLServerSocket(int portno)
  50:	        throws java.io.IOException
  51:	    {
  52:	        SSLServerSocket ss;
  53:	        SSLServerSocketFactory ssf = (SSLServerSocketFactory)
  54:	            SSLServerSocketFactory.getDefault();
  55:	        ss = (SSLServerSocket) ssf.createServerSocket(portno);
  56:	        return( ss );
  57:	    }
  58:	    static java.io.BufferedReader stdin = 
  59:	        new java.io.BufferedReader( new java.io.InputStreamReader(System.in) );
  60:	    static java.io.PrintStream stdout = System.out;
  61:	    static java.io.PrintStream stderr = System.err;     
  62:	}
% diff EchoServer.java SSLEchoServer.java [←]
2,3c2,3
<       EchoServer.java -- ハクサホ、チシソョ、ケ、・オ。シ・ミ(TCP/IP, Javaネヌ)
<       ~yas/syspro/ipc/EchoServer.java
---
>       SSLEchoServer.java -- ハクサホ、チシソョ、ケ、・オ。シ・ミ(SSLネヌ)
>       ~yas/syspro/ipc/SSLEchoServer.java
8a9
> import javax.net.ssl.*;
10c11
< class EchoServer
---
> class SSLEchoServer
15c16
<           System.err.println("Usage: % java EchoServer port");
---
>           System.err.println("Usage: % java SSLEchoServer port");
24c25
<       ServerSocket acc = new ServerSocket( portno );
---
>       ServerSocket acc = makeSSLServerSocket( portno );
38c39
<       stdout.println("run telnet "+hostname+" "+portno );
---
>       stdout.println("run openssl s_client -host "+hostname+" -port "+portno );
46a48,56
>     }
>     static SSLServerSocket makeSSLServerSocket(int portno)
>       throws java.io.IOException
>     {
>       SSLServerSocket ss;
>       SSLServerSocketFactory ssf = (SSLServerSocketFactory)
>           SSLServerSocketFactory.getDefault();
>       ss = (SSLServerSocket) ssf.createServerSocket(portno);
>       return( ss );
% []

◆keytoolによる秘密鍵と証明書の生成

% ls -l ./echo.keystore [←]
ls: ./echo.keystore: No such file or directory
% keytool -genkey -keystore ./echo.keystore -storepass "open sesame" -alias echo -keypass "open sesame" [←]
What is your first and last name?
  [Unknown]:  Yasushi Shinjo[←]
What is the name of your organizational unit?
  [Unknown]:  Colleage of Information Sciences[←]
What is the name of your organization?
  [Unknown]:  University of Tsukuba[←]
What is the name of your City or Locality?
  [Unknown]:  Tsukuba[←]
What is the name of your State or Province?
  [Unknown]:  Ibaraki[←]
What is the two-letter country code for this unit?
  [Unknown]:  JP[←]
Is CN=Yasushi Shinjo, OU=Colleage of Information Sciences, O=University of Tsuku
ba, L=Tsukuba, ST=Ibaraki, C=JP correct?
  [no]:  yes[←]

% ls -l echo.keystore [←]
-rw-r--r--    1 yas      lab          1336 Feb 25 20:02 echo.keystore
% keytool -list -keystore ./echo.keystore [←]
Enter keystore password:  

  WARNING WARNING WARNING  *****************
 The integrity of the information stored in your keystore  *
 has NOT been verified!  In order to verify its integrity, *
 you must provide your keystore password.                  *
  WARNING WARNING WARNING  *****************

Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

echo, Feb 25, 2006, keyEntry,
Certificate fingerprint (MD5): 77:8D:83:43:A8:25:9A:9A:F6:CA:44:CB:24:7C:79:67
% []
keytool -genkey で、秘密鍵と公開鍵の組が作られる。秘密鍵は、暗号化され る。公開鍵は、X509証明書の形で保存される。公開鍵は、暗号化は行われてい ない。keytool -list でパスワードを与えなくても表示される。

◆サーバの実行

サーバを実行する時には、秘密鍵を含む keyStore と秘密鍵を解くためのパス ワードを与える。
% javac SSLEchoServer.java [←]
% java -Djavax.net.ssl.keyStore=./echo.keystore -Djavax.net.ssl.keyStorePassword="open sesame" SSLEchoServer 1231 [←]
run openssl s_client -host adonis9.coins.tsukuba.ac.jp -port 1231
connection (hash==19300430) from 127.0.0.1:36269
received (hash==19300430) 8 characters, [1st line]
received (hash==19300430) 8 characters, [2nd line]
received (hash==19300430) 3 characters, [bye]
connection (hash==19300430) closed.
^C
% []
サーバは自動的には停止しないので、最後は^Cで止める。 ポート番号としては、適当に外の人とぶつからないものを与える。

◆クライアントの実行

クライアントを実行する時には、証明書を含んだ trustStore のファイルを指 定する。SSL で接続する時、サーバがこのファイルに含まれてる公開鍵と同じ ものを提示した時には、信用する。keystore に対するパスワードは不用である。
% javac SSLEchoClient.java  [←]
% java -Djavax.net.ssl.trustStore=./echo.keystore SSLEchoClient localhost 1231 [←]
==> 1st line[←]
sending: [1st line]
received: [1st line]
==> 2nd line[←]
sending: [2nd line]
received: [2nd line]
==> bye[←]
sending: [bye]
received: [bye]
==> ^D
% []
クライアント側は、keystore 全体は不用である。公開鍵を含む証明書だけが あればよい。正式な方法は、keystore ファイルから keytool -export で証明 書を取り出し、別の keystore ファイルに -import で取り込むことである。 しかし、秘密鍵は暗号化されてるので、上のように秘密鍵を含んだままの keystore のファイルをコピーして与る方法もある。

OpenSSL で作成した秘密鍵や証明書を、Java の keystore 形式に変換するこ ともできる。

[JavaHouse-Brewers:51476] Re: 秘密鍵をkeytool で 扱える形式への変換方法
http://java-house.jp/ml/archive/j-h-b/051472.html

◆プログラミング(in C)

Socket で書かれたプログラムを簡単に SSL 対応に書き換えられる。

Socket 版

/* Returns the number of characters successfully written */ size_t write(int file_descriptor, void *buf, size_t len)

OpenSSL 版

/* Returns the number of characters successfully written */ int SSL_write(SSL *socket_info, char *buf, int len)

実際には、秘密鍵や証明書の設定がめんどくさい。そうするよりも、stunnel コマンドをパイプ経由で実行した方が楽である。

p = run_cmd("stunnel -c -r 192.168.100.1:imap2 -A /etc/ca_certs -v 3");
http://www-06.ibm.com/jp/developerworks/security/011005/j_s-stun.html

■SSH (Secure Shell)

Unix r系コマンドの置き換え。 トンネリング。暗号化された通信路を作り、その中を他の通信プロトコルを通 す。

◆r系コマンドの弱点

IP spoofing (なりすまし).

rsh のセッションで行われるであろうパケットを偽造する。

IP アドレスでホストを認証すると危ない。

DNS spoofing.

偽のDNSのサーバを立てる。

◆SSHでの解決方法

ホストの認証を、IP アドレスではなく、公開鍵で行う。

サーバは、2つの鍵と64ビットの乱数を送る。 クライアントは、乱数を送り返す。 乱数が一致したら、IP spoofing されていない。

クライアントは、セッション鍵(対称暗号系の鍵)をサーバの2つの公開鍵で 暗号化して送る。

対象暗号の鍵(セッション鍵)を生成し、公開鍵で送る。

これ以降の通信は、セッション鍵で暗号化される。

◆SSHでのユーザの認証

暗号化された通信絽が確立された後は、パスワードを流しても安全。

個人ごとに公開鍵での認証機能を利用したほうがよい。

◆トンネリング(port forwarding)

SSH で暗号化された通信路の中に一般のアプリケーションの通信を通す。 SSH 用語では、port forwarding という。

よくつかわれるもの。

使い方:

% cat bin/ssh-coins-mail [←]
#!/bin/sh
host=mail.coins.tsukuba.ac.jp
ssh -L 10143:$host':'143 -L 10110:$host':'110 -L 10025:$host':'25 $host $*
% []

自分自身(localhostが便利)のポート番号10143, 10110, 10025 に来た接続要 求を、リモートの host の143, 110, 25 に転送する。ssh の接続先(最後の $host)と、-L で指定するホストは必ずしも一致していなくてもよい。 ssh コマンドは、Unix、MacOSX、Cygwin で使える。Windows の TeraTerm や PuTTY でも使える。

図 ssh によるトンネリング(SMTP、POP、IMAP)

図 ssh によるトンネリング(SMTP、POP、IMAP)

以下は、上のコマンドを実行して作成したトンネルを使って、IMAP を使って coins のメール・サーバへアクセスした様子である。
 % telnet localhost 10143[←]
 Trying 127.0.0.1...
 Connected to localhost.
 Escape character is '^]'.
 * OK [CAPABILITY IMAP4REV1 LOGIN-REFERRALS STARTTLS AUTH=LOGIN] orchid-a.coins.tsukuba.ac.jp IMAP4rev1 2001.315rh at Sun, 13 Feb 2005 23:52:48 (JST)
 * login yas XXXXXXXX[←]
 * OK [CAPABILITY IMAP4REV1 IDLE NAMESPACE MAILBOX-REFERRALS SCAN SORT THREAD=REFERENCES THREAD=ORDEREDSUBJECT MULTIAPPEND] User yas authenticated
 * select #mh/inbox[←]
 * 144 EXISTS
 * 0 RECENT
 * OK [UIDVALIDITY 1046618627] UID validity status
 * OK [UIDNEXT 145] Predicted next UID
 * NO [UIDNOTSTICKY] Non-permanent unique identifiers: #mh/inbox
 * FLAGS (\Answered \Flagged \Deleted \Draft \Seen)
 * OK [PERMANENTFLAGS ()] Permanent flags
 * OK [UNSEEN 144] first unseen message in #mh/inbox
 * OK [READ-WRITE] SELECT completed
 * logout[←]
 * BYE orchid-a.coins.tsukuba.ac.jp IMAP4rev1 server terminating connection
 * OK LOGOUT completed
 Connection closed by foreign host.
 % []

◆SSH1の弱点

SSH1 には、プロトコル上、いくつかの弱点が見つかっている。

SSH2 を使った方がよい。

RSA社が提唱している公開鍵を使ってセッション鍵(秘密鍵)を交換する 方式(PKCS1 1.5 )そのものに、脆弱性がある [1]。

PKCS -- Public-Key Cryptography Standards

[1] Daniel Bleichenbacher, "Chosen ciphertext attacks on RSA encryption standard PKCS #1", Advances in Cryptology, CRYPTO 98. Springer.

サーバ鍵を1時間に1回しか変えない。

SSH 1.5 は、1024 ビットの鍵を使っている。 これを破るには、2 20 + 2 19 回接続でよい。毎 秒、約 400 回。

1個所からの接続に上限を付ける。OpenSSH はそうなっている。 Distributed 攻撃には、弱そう。

OpenSSH
http://www.openssh.org/

◆sshにおける公開鍵による認証

SSH では、公開鍵暗号を使った利用者認証 が使える。

準備

利用

Unix のパスワードを利用する方法と比較した時の利点

◆ssh-agentの利用

ssh-agent を使えば、ログイン時には、パスフレーズを打たないでログインで きるようになる。
% ssh-agent tcsh [←]
% printenv SSH_AUTH_SOCK  [←]
% ssh-add -l [←]
		ssh-agentが有効なこと確認
% ssh-add [←]
                鍵の登録
% ssh-add -l [←]
	        鍵が登録されたことの確認
% ssh remote1 [←]
% ssh remote2 [←]
% ssh remote3 [←]
                利用
% exit [←]
                ssh-agentが有効な tcsh の終了
% []
ssh-agent にコマンド(上の例ではtcsh)を与える代りに、csh の環境変数を設 定させるコマンドを出力させ、eval で実行する方法もある。
% eval `ssh-agent` [←]
% printenv SSH_AUTH_SOCK [←]
<以下同じ>
ただし、この方法では、ssh-agent のプロセスが残ってしまう。ssh-agent の 実行を .login などに入れる時には、.logout で ssh-agent -k を実行し、殺 すようにする。


Last updated: 2006/02/28 03:28:32
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>