暗号、SSL、SSH

分散システム

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

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

■参考文献

■暗号

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

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

図? 暗号の考え方

図? 暗号の考え方

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

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

◆鍵を使うことの重要性

問: 答え:

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

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

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

◆暗号の経済学

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

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

図? 指数関数

図? 指数関数

図? 指数関数

図? 指数関数

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

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

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

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

◆Caesar暗号

Caesar暗号は、置換暗号(substitution cipher)の1つ。置換暗号では、各 文字あるいは文字群が、それぞれ別の文字あるいは文字群に置換される。

Caesar暗号は、知れている最後の暗号である。 平文アルファベットをN文字ずらした暗号文アルファベットに変える。

N=2 の時の対応表

abcdefghijklmnopqrstuvwxyz
CDEFGHIJKLMNOPQRSTUVWXYZAB
暗号の説明では、平文を小文字で、暗号文を大文字で書く習慣がある。

N=13 で、大文字小文字を保存する方法を、rot13 暗号という。rot13 は、電 子メールやネットワーク・ニュースで「ネタばらし」の部分を書く時に使われ る。

漢字の場合、rot47 という方法がある。nkf -r で、rot13/47 が使える。

◆乱数(random numbers)

数の集合から、無作為抽出で抜き出された数。

真性乱数。ビット列にすると、0と1の発生確率がそれぞれ1/2で、各ビッ トは他の部分と独立(iid(independent and identically distributed)) である。

物理乱数。量子力学の効果を増幅してディジタル化したもの。 平滑化して0,1のバランスをとれば、真性乱数になる。

疑似乱数(pseudo random number)。種(seed)と呼ばれる入力ビットパタンを基 に計算された、種よりも長いランダムに見えるビット・パタン。種が決まれば 出力乱数は一意に決まる。

◆乱数を使った暗号

Caesar暗号では、定数だけずらしていた。定数ではなく、文字の長さの乱数の 列を使い、文字ごとに乱数の数だけだけずらす。

例:

乱数表: 0 18 19 22 22  7  9  4 14  3
 平文: h  e  l  l  o  w  o  r  l  d
        8  5 12 12 15 23 15 18 12  4
暗号文: H  W  E  H  K  D  X  V  Z  G
   : 8 23  5  8 11  4 24 22 26  7
乱数表そのものや、大きな乱数表の中でどこから使い始めるかを鍵にすること ができる。

真性乱数を使うと、解読する方法は数学的に存在しないことが証明されている。

しかし、真性乱数を使うことはコストが大きい。 送信側と受信側で同じ真性乱数を作るのが大変である。

乱数表を記憶する変わりに、疑似乱数を使う方法がある。使う疑似乱数の性質 が悪いと簡単に解読される。

実際には、文字をずらすのではなく、足し算、引き算や、排他的論理和と呼ば れる計算が使われることが多い。

◆転置暗号

Caesar暗号や乱数を用いる暗号では、平文の文字の順序を変えずに、文字を置き換 える。これを置換暗号という。これにたいして、転置暗号(transposition cipher)では、平文の文字の順序を入れ替えるが、文字の置き換えは行わない。 (下の例では、大文字小文字が変わっているが、これは暗号化の説明のために 変えて書いているだけである。)

次は、転置暗号の1つ、コラム転置の例である。キーは、同じ文字を含まない 1個の単語や熟語である。このキーでコラムに番号付けをする。たとえばコラ ム1は、アルファベットで先頭に近い文字の下のコラムとなる。

MEGABUCK
--------
74512836
--------
pleasetr
ansferon
emillion
dollarst
omyswiss
bankacco
untsixtw
otwoabcd
 平文: pleasetransferonemilliondollarstomyswissbankaccountsixtwotwo
暗号文: AFLLSKSOSELAWAIATOOSSCTCLNMOMANTESILYNTWRNNTSOWDPAEDOBUOERIRICXB

◆DES

DES(Data Encryption Standard)は、アメリカ商務省標準局 (NBS, National Bureau of Standard, 現在のNIST, National Institute of Standrds and Technology)が1977年に定めた暗 号標準である。IBM社による提案が元になっている。DESは、 アメリカ政府内で、コンピュータ・データのうち、非機密だが取扱 い注意(unclassified but sensitive)のデータを暗号化するため の標準である。DESを一般の商用にも使うことを推奨している。 たとえば、UNIXのパスワード・ファイルは、DESにより暗号 化されている。

DESは、対称暗号系(慣用暗号系)の1つであり、暗号化と復号 化に同一の鍵(56ビット)を用いる。DESは、転時暗号の一種 である。転時暗号では、平文の文字の順序(コンピュータでは、ビッ ト)を入れ替えるものである。DESでは、64ビットの平文につ いて、鍵をもとにビットの入れ替えを16段繰り返す。

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:
            86:40:d8:09:c3:e1:1c:2a:1c:ba:17:3e:c2:45:a1:97
        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 22 00:00:00 2004 GMT
            Not After : Nov 22 23:59:59 2005 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 $50, CN=www3.coins.tsukuba.ac.jp
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:e2:77:f6:76:11:d3:61:81:7e:05:f8:83:33:44:
                    8a:a3:5c:74:af:c3:ca:0b:03:73:db:25:94:75:98:
                    c2:f4:c4:0e:99:71:58:ce:5a:e5:5a:a5:29:ec:c0:
                    f7:0e:08:9e:22:9d:36:ec:df:43:11:b8:43:92:d5:
                    e3:54:ef:e3:0e:8e:d8:8d:46:1e:3e:13:75:c4:7a:
                    0e:41:19:a9:75:4e:19:9d:15:88:85:be:52:50:63:
                    96:33:05:ba:a7:61:fc:69:93:48:9a:29:c7:b1:5a:
                    f9:14:f9:11:71:f3:bd:0a:10:89:f1:ff:05:7b:5e:
                    9e:1e:b4:fb:d1:2c:9e:bc:03
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier: 
                keyid:F6:52:22:17:15:13:08:03:59:BF:18:95:9F:48:B4:B9:E9:FE:F8:66

            X509v3 Subject Key Identifier: 
                45:57:9E:45:12:07:3D:F9:1C:1A:9B:40:42:96:F2:39:9C:69:EF:64
            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
            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_2.crl
                URI:http://crl.comodoca.com/Class3SecurityServices_2.crl
                email:Class3SecurityServices_2@crl.comodo.net

            Netscape Cert Type: 
                SSL Client, SSL Server
    Signature Algorithm: sha1WithRSAEncryption
        0d:83:03:eb:10:40:83:e2:ee:cd:51:88:f1:6c:ce:0b:45:a7:
        30:68:7e:e3:09:f0:40:7b:ad:2f:f7:4c:37:3c:5a:44:93:fb:
        0a:fb:d3:35:f6:4b:93:9c:54:95:33:98:45:f9:5b:14:07:19:
        5a:0a:eb:05:d6:0d:b0:62:87:d2:4f:12:de:7a:5d:62:66:8d:
        1b:13:9d:f7:83:6d:dd:c8:45:96:7e:3a:fe:1a:85:59:de:4d:
        15:4b:90:41:a7:bc:70:3b:05:25:7a:ee:9f:d6:86:13:5a:bb:
        98:98:ae:5c:ee:3c:1d:69:d7:ee:3b:8a:85:e2:0a:ed:e8:22:
        48:d8:5b:ea:de:15:2e:a2:51:1f:cb:10:cb:56:d0:cc:de:36:
        70:cf:c8:43:d3:85:cc:fa:f0:52:ac:70:11:55:32:f8:7e:08:
        72:0f:82:ab:db:cd:ef:2a:b9:fa:0b:10:11:5b:eb:14:92:16:
        01:3b:b9:c3:db:f6:fd:df:5e:b5:13:96:a8:7b:76:b4:97:64:
        d2:69:3e:84:e7:27:72:59:dc:63:78:bd:0c:56:db:c3:a8:04:
        a5:92:0e:0c:32:ed:30:f1:80:7b:06:18:bc:8c:f2:a6:a9:ab:
        02:05:a5:42:d2:83:26:e0:9b:1d:7f:f6:b1:57:4a:3a:c5:ae:
        8c:36:6f:63
% []

◆認証局の階層

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

認証局(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 $50/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/CN=GTE CyberTrust Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFgzCCBGugAwIBAgIRAIZA2AnD4RwqHLoXPsJFoZcwDQYJKoZIhvcNAQEFBQAw
gdwxCzAJBgNVBAYTAkdCMRcwFQYDVQQKEw5Db21vZG8gTGltaXRlZDEdMBsGA1UE
CxMUQ29tb2RvIFRydXN0IE5ldHdvcmsxRjBEBgNVBAsTPVRlcm1zIGFuZCBDb25k
aXRpb25zIG9mIHVzZTogaHR0cDovL3d3dy5jb21vZG8ubmV0L3JlcG9zaXRvcnkx
HzAdBgNVBAsTFihjKTIwMDIgQ29tb2RvIExpbWl0ZWQxLDAqBgNVBAMTI0NvbW9k
byBDbGFzcyAzIFNlY3VyaXR5IFNlcnZpY2VzIENBMB4XDTA0MTEyMjAwMDAwMFoX
DTA1MTEyMjIzNTk1OVowggEMMQswCQYDVQQGEwJKUDERMA8GA1UEERMIMzA1LTg1
NzMxEDAOBgNVBAgTB0liYXJha2kxEDAOBgNVBAcTB1RzdWt1YmExGDAWBgNVBAkT
DzEtMS0xLFRlbm5vaGRhaTEeMBwGA1UEChMVVW5pdmVyc2l0eSBvZiBUc3VrdWJh
MSgwJgYDVQQLEx9Db2xsZWdlIG9mIEluZm9ybWF0aW9uIFNjaWVuY2VzMSEwHwYD
VQQLExhQcm92aWRlZCBieSBUb3JpdG9uLEluYy4xHDAaBgNVBAsUE1Rvcml0b24s
SW5jIFNTTCAkNTAxITAfBgNVBAMTGHd3dzMuY29pbnMudHN1a3ViYS5hYy5qcDCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4nf2dhHTYYF+BfiDM0SKo1x0r8PK
CwNz2yWUdZjC9MQOmXFYzlrlWqUp7MD3DgieIp027N9DEbhDktXjVO/jDo7YjUYe
PhN1xHoOQRmpdU4ZnRWIhb5SUGOWMwW6p2H8aZNIminHsVr5FPkRcfO9ChCJ8f8F
e16eHrT70SyevAMCAwEAAaOCAY8wggGLMB8GA1UdIwQYMBaAFPZSIhcVEwgDWb8Y
lZ9ItLnp/vhmMB0GA1UdDgQWBBRFV55FEgc9+Rwam0BClvI5nGnvZDAOBgNVHQ8B
Af8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB
BQUHAwIwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwQwKzApBggrBgEFBQcCARYd
aHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwgbAGA1UdHwSBqDCBpTA4oDag
NIYyaHR0cDovL2NybC5jb21vZG8ubmV0L0NsYXNzM1NlY3VyaXR5U2VydmljZXNf
Mi5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NsYXNzM1NlY3Vy
aXR5U2VydmljZXNfMi5jcmwwLaAroCmBJ0NsYXNzM1NlY3VyaXR5U2VydmljZXNf
MkBjcmwuY29tb2RvLm5ldDARBglghkgBhvhCAQEEBAMCBsAwDQYJKoZIhvcNAQEF
BQADggEBAA2DA+sQQIPi7s1RiPFszgtFpzBofuMJ8EB7rS/3TDc8WkST+wr70zX2
S5OcVJUzmEX5WxQHGVoK6wXWDbBih9JPEt56XWJmjRsTnfeDbd3IRZZ+Ov4ahVne
TRVLkEGnvHA7BSV67p/WhhNau5iYrlzuPB1p1+47ioXiCu3oIkjYW+reFS6iUR/L
EMtW0MzeNnDPyEPThcz68FKscBFVMvh+CHIPgqvbze8qufoLEBFb6xSSFgE7ucPb
9v3fXrUTlqh7drSXZNJpPoTnJ3JZ3GN4vQxW28OoBKWSDgwy7TDxgHsGGLyM8qap
qwIFpULSgybgmx1/9rFXSjrFrow2b2M=
-----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 $50/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 3202 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: AF00E36437303566FB4DF1B56AFCA493E47C102D7FEB552268D9868FFE79CF11
    Session-ID-ctx: 
    Master-Key: 27150509A5118C95B97E098A0A9903685050D34E83DFB4C990517A6179248216DEF6FDCA635C378D4F59A8C7DD0F05B2
    Key-Arg   : None
    Start Time: 1108296834
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
GET /~yas/ HTTP/1.0[←]
[←]
HTTP/1.1 200 OK
Date: Sun, 13 Feb 2005 12:14:10 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 telnet "+hostname+" "+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 );
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          1338 Feb 13 21:32 ./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 13, 2005, keyEntry,
Certificate fingerprint (MD5): 88:12:24:44:88:FE:A9:CF:2E:E1:A0:C1:47:0E:B9:2D
% []
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 telnet adonis9.coins.tsukuba.ac.jp 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-6.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: 2005/02/21 16:32:05
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>