| THIS IS A PEN |
例として、以下の表にしたがって文字を置きかえる事によって暗号化を行なう。
| ABCDEFGHIJKLMNOPQRSTUVWXYZ
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ RSN IUBZKXMWOTCEVYQFAHLJPGD |
すなわち、TをFに置き換え、HをZに置き換え…、といった様に文中の文字を置き換えていく。
結果は以下のようになる。
| FZKQDKQDRDEIT |
ここで、暗号化前の文を平文(Plain TextまたはClear Text)、暗号化後の文を暗号文(Cipher Text)と呼ぶ。
暗号文を元の平文に戻すには、文字の置き換えを逆に辿れば良い。
| ABCDEFGHIJKLMNOPQRSTUVWXYZ
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ RSN IUBZKXMWOTCEVYQFAHLJPGD |
暗号文を上記表にしたがって変換すると、元の平文を取得できる。暗号文から平文を得る事を復号化(Decrypt)と呼ぶ。
二者間で文書を暗号化して授受するには、あらかじめ“RSN IUBZKXMWOTCEVYQFAHLJPGD”という文字列を二者間で合意しておけば良い。悪意ある第三者(Tamper)に対してこの文字列をもらしさえしなければ、通信経路が盗聴される可能性があったとしても、安全(Secure)な情報交換を行なう事ができる。このように、暗号化・復号化を行なうために必要な情報を鍵(Key)と呼ぶ。上記例では、鍵は“RSN IUBZKXMWOTCEVYQFAHLJPGD”という文字列である。第三者は、この鍵を知らない限り暗号化された文章を復号化する事ができない。
上記の暗号化方法では、暗号化と復号化のそれぞれの処理で同一の鍵を使用している。このような暗号化の方法を、対称暗号方式(Symmetric Cryptography)と呼ぶ(共通鍵暗号方式、秘密鍵暗号方式、慣用暗号方式とも呼ばれる)。暗号化と復号化で異なる鍵を使用する方法もあり、これは非対称暗号方式(Asymmetric Cryptography)と呼ぶ(公開鍵暗号方式とも呼ばれる)。非対称暗号方式については後述する。
対称暗号方式における鍵は、場面によって対称鍵(Symmetric Key)、共通鍵・共有鍵(Session
Key)、秘密鍵(Secret Key)などと呼ばれる。
| メモ:実際には、このような単純な文字の置き換えによる暗号文は、文字が出現する頻度などの統計的性質を元に容易に解読される。 |
暗号化の方法としては、以下のような方法も考えられる。
| THIS IS A PEN |
上記平文を4文字ごとのブロックに分割し、各ブロックに対して以下の変換を施す。
| 1番目の文字を3番目の文字と入れ替える。
2番目の文字を1番目の文字と入れ替える。 3番目の文字を4番目の文字と入れ替える。 4番目の文字を2番目の文字と入れ替える。 |
例えば最初のブロックは「THIS」であり、Tが3番目、Hが1番目、Iが4番目、Sが2番目に来るように入れ替えを行なう。ただし、平文の文字数が4の倍数でないので、末尾に空白文字を足す。
結果は以下の通りとなる。
| HSTII S EAP N |
この暗号化方法の場合は、“3142”という情報を鍵として考える事ができる。
このように平文をブロックに分けて暗号化を行なう方式をブロック暗号方式と呼ぶ。これに対して、平文をブロックに分けることなく暗号化を行なう方式をストリーム暗号方式と呼ぶ。ブロック暗号方式の場合は、平文の文字数をブロック長の倍数に合わせるように、末尾に文字を足すなどの処理を行なう必要がある。例えば上記の例では空白文字を足した。このように、ブロック暗号方式において文字を足す事をパディング(Padding)と呼ぶ。
現在実用的に使用されている対称暗号方式は、基本的には上記のような換字・転字の延長と考えて良い。ただし、暗号アルゴリズムが分かっていたとしても鍵を知らない限りは解読が困難であるように設計されており、これは現代的な暗号技術の特徴でもある。
| メモ:1990年に、この種の対称暗号方式は使用する内部テーブル(S-BOX)の設計によっては脆弱性がある事が発見された(差分攻撃法)。ところがDESはその15年近くも前に設計されたにも関わらず、既にこの脆弱性への対処がなされている事が明らかになった。 |
まず、e、d、nを以下のように定める。
暗号文 = 平文のe乗をnで割った余り。
復号文 = 暗号文のd乗をnで割った余り。
すなわち、eとnの組が暗号用の鍵、dとnの組が復号用の鍵と考えられる。
暗号用の鍵を元に復号用の鍵を得る、すなわち、eとnを元にdを算出する事は困難である事が知られている。これを行なうには、nを因数分解し、pとqを求める必要があるが、因数分解を効率よく行なう数学的手法は発見されていないため、nが何百桁もの桁数となる場合、現在の技術では因数分解を行なう事は不可能である。
※逆に素数を効率よく探す方法はいろいろな種類のものが知られていて、特に確率的手法を用いるとほぼ多項式時間で求める事が可能である。
このような非対称暗号方式を用いると、対称暗号方式とは異なるパラダイムによって暗号通信を行なう事ができる。次節で非対称暗号方式による通信の方法を述べる。
なお、実際のpやqは、中国人剰余定理(CRT)に対応した値が選ばれる。
| メモ:現時点での最新の暗号解読結果は1999年にRSA Factoring Challengeが行なった512ビットのRSA鍵の暗号解読である。また、今年(2000年)4月17日に楕円曲線暗号と呼ばれる非対称暗号方式について109ビットの鍵による暗号の解読に成功している。これは、RSAでは600ビット以上の鍵に相当する計算量であると見積もられている。 |
ここで、公開される暗号用の鍵を公開鍵(Public Key)、秘密にされる復号用の鍵を秘密鍵または私有鍵(Private Key)と呼ぶ。秘密鍵と公開鍵を合わせて鍵ペア(Key Pair)と呼ぶ。
秘密鍵はそのままの状態で保管される事は危険なので、通常パスワード暗号化などを施した上で保管される。これを、鍵をパスワードでラップ(Wrap)すると言う(ロックするとも言う。特にICカードの分野などで、鍵をラップするため(に限らないが)のパスワードをPINと呼ぶことがある)。ラップされていない鍵を、生(Raw)の鍵と言う。
| メモ:対称鍵暗号方式は雨後の竹の子のごとくさまざまな種類のものが発明されつづけているが、これに比べて非対称暗号方式は因数分解に基づくものと離散対数に基づくものに大別され、種類は対称暗号方式程は多くない。日本では例えばNTTがEPOCその他の非対称暗号方式を発表しており、このEPOCの解読は素因数分解と同等の困難性があることが証明されている(RSAはこの点が未だ証明されていない)。 |
まったく別の方法として、DH鍵交換(配送・共有とも言う)方式を使用する方法もある。これは、通信を行なう二者が、第三者に知られる事無く同一の対称鍵を生成する方法である。DH鍵交換の場合は、数学的には以下のような処理を行なう。
第三者は、秘密鍵であるaやbが分からない限り暗号を解く事はできない。公開鍵を元にaを求めるには、「gを底とした公開鍵の離散対数(の結果がa)」を求めなければならないが、現在これを効率よく求める方法は知られていない。(なお、単純なDH方式は「中間者攻撃」を防ぐことができない)
同様の鍵交換方式として、上記DHを楕円曲線上の演算に応用した楕円DH(ECDH)方式が存在する。
| メモ:人を表すのにこれまでAやBという表記を用いてきた。セキュリティ系の文書では、これに代えてしばしばAliceやBobという表現が用いられる。 |
第三者が、Aの公開鍵によって正しく復号化できるような暗号文を作成するためには、対応する秘密鍵を入手しなければならない。つまり逆に、Aが秘密鍵を安全に保管している限り、第三者は正しい暗号文を偽造する事ができない。
上記手順中で、Sはメッセージの正当性を保証するデータであり、現実世界における署名捺印に相当するものである。このため、暗号技術の世界では特にSを電子署名(Digital Signature)と呼ぶ。
電子署名方式には、RSA署名方式のほかにESIGN、エルガマル署名方式、DSA(エルガマル署名の改造版。DSS(米標準の電子署名方式)に選ばれたため、DSSとも呼ぶ)、楕円DSA(ECDSA)などがある。ESIGNなどはRSAとは異なり署名に特化したアルゴリズムで、暗号化に使用する事はできない。
| メモ:DSSはNSA(米国家安全保障局)の手が入っていることからさまざまな噂が流れた。例えばDSSで使用するパラメータについて、公表された値が「奇妙」な性質を持っているため、何らかの裏口(back
door)を持つのではないかと騒がれた。
NSAは、セキュリティの世界では悪名高い。その活動が公表されることはあまりないが、世界最高の暗号学者と施設を備え、NSAが輸出を許可した暗号製品はすべて解読可能だと信じている人もいる。最近では世界規模の盗聴ネットワーク「エシュロン」の騒動が記憶に新しい。 |
メッセージダイジェストは、平文Mを「縮めた」ものである。例として、以下の平文をMD5というアルゴリズムを使用して縮める。
| A signature primitive produces a signature representative from a message representative under the control of a private key, and a verification primitive recovers the message representative from the signature representative under the control of the corresponding public key. One pair of signature and verification primitives is employed in the signature schemes defined in this document and is specified here: RSASP1/RSAVP1. |
結果は以下の16バイトのデータとなる。このデータは、メッセージダイジェスト、ダイジェスト、またはハッシュ(Hash)などと呼ばれる。
| CB E7 25 C8 8A CD EB 45 62 C3 B8 70 D1 D3 DF 16 |
※公開鍵に対するハッシュはKey Finger Printと呼ばれる。例:署名検証用公開鍵をWebで公開しておき、電子メールや名刺などに公開鍵のFinger Printを記載するように習慣付けておく。他者がWebから取得した公開鍵の正当性を判断したい場合、取得した鍵のFinger Printを計算し、これまで受け取ったメールなどに記載されていたFinger Printと比較して、一致すれば本人の公開鍵であると判断する。
理論上は、異なる二つの文が同一のダイジェストを持つことがありえるが、実際には二つの文が偶然同一のダイジェストとなる確率は極めて低いため、ありえないと考えて良い。また、例えばあるMD5ダイジェスト値が与えられたとき、このダイジェストを持つ平文を作成する方法は知られていない。
この事から以下のような、計算量の少ない電子署名方式を考える事ができる。
ダイジェストを使用する通常の署名方式では、使用するダイジェストのアルゴリズムと暗号化方式を組み合わせて署名アルゴリズムを表記する。例えばダイジェストアルゴリズムにMD5、暗号化方式にRSAを使用した場合、MD5WithRSA(ASN.1のOID)といった表記をする場合がある。
有名なダイジェストアルゴリズムには、MD5のほかにSHA1などがある。
| メモ:MDシリーズにはMD2、MD4、MD5などがある。MD5はよく使用されるが、1996年に理論上の脆弱性がある事が指摘された。MD3は、実際に使用される前にMD4に取って代われた。 |
複数のデータに対して電子署名を行なう場合、各データ一つ一つに対して電子署名を生成する代わりに、各データのダイジェストを求め、そのダイジェストのリストに対して電子署名を生成する場合がある。この場合のダイジェストのリストは、目録(manifest)と呼ばれることがある。
・パスワードのダイジェスト値を求める。
・求めたダイジェストの先頭56bitを切り取り、これをDESの鍵とみなして、平文を暗号化する。
※セキュリティの分野では、パスワードとして単語ではなく(より長い)文章を想定することがある。このため、パスワードという言葉の代わりにしばしばパスフレーズ(PassPhrase)という言葉が使用される。
パスワード暗号化の際には、単にパスワードのダイジェスト値を求める代わりに、パスワードに前もって8バイト程度のデータ(ソルト-Saltと呼ばれる)を追加してからダイジェスト値を求める事により、より撹乱された鍵を生成されるようにする事がある。また、単純にダイジェスト値を求めるのではなく、「ダイジェスト値のダイジェスト値」を求めるといったように、ハッシュ関数を繰り返し適用する場合がある(繰り返しの回数はIteration Countと呼ばれる)。
MACの具体的な例としては、例えばメッセージをDES鍵で暗号化し、その暗号文のMD5ダイジェスト値をMACとして採用する、といった方法がある。
この場合、公開鍵と、それに対する電子署名は常にペアで扱われるので、手間を省くために通常電子証明書の中身には公開鍵と電子署名が両方含まれる。そこで、メッセージMに対する署名Sを検証したい場合、「電子証明書Cによって署名Sを検証する」という言い回しをすることがある。これは、「電子証明書Cの中身に含まれる署名検証用公開鍵によって署名Sを検証する」という意味である。
この他電子証明書の中身には通常、証明書の有効期限や証明書発行者の名前(実際にはDNなど)などの情報が含まれている。
※DNの形式には色々あるが、例えば"CN=MASAPICO,OU=TOKYO,O=COOL,C=JP"などといった形でエンティティを特定する。
上記例で、Cが公開している公開鍵自体に対して、より信頼できる別のCAが証明書を発行する事がある。このような連鎖を辿っていった時の一番上位のCAをルートCA(Root CA)と呼ぶ。また、証明書を同様に辿る事により、一連の証明書の列ができるが、これをCertificate Chainと呼ぶ。一番上位の証明書はルート証明書と呼ばれる。ルート証明書は慣例的に自分自身の公開鍵によって署名を行なう。つまり、自己署名型証明書(self-signed certificate)になっている。
CAは、何らかの理由(例えば有効期限切れ)で無効になった証明書(のシリアル番号)のリストを配布する。これを証明書廃棄リスト(Certificate Revocation List)またはCRLと呼ぶ。
なお、CAの機能の一部を代行するRAというのもある。例えば、ユーザの代理で証明書の発行申請を行なう。
| メモ:CAとしてはVeriSign社などが有名。ルートCAなどの証明書は製品にあらかじめ組み込まれている事がある。例えばInternet ExplorerやNetscapeはいずれもいくつかのCAの証明書が組み込まれており、メニューから辿っていくとそれらの証明書を表示する事ができる。使用しているブラウザが古い場合、証明書も期限切れのものが多くなっているだろう。 |
RSAPublicKey ::= SEQUENCE {
n INTEGER,
e INTEGER}
つまり、RSA公開鍵はnとeからなるということを表している。
ASN.1で表記された情報をバイナリのデータ列で表す方法として、BER(Basic Encoding Rules)という方法が定められている。実際には、BERを簡略化したDER(Distinguished Encoding Rules)がよく使用されている。DERはBERのサブセットであり、DERエンコーディングされたデータは、BERエンコーディングされたデータでもある。
上記RSAPublicKeyについてn=15、e=5の場合、以下のようにDERエンコードされる。つまり、PKCS#1にしたがってこの公開鍵を受け渡しするには、“30
06 02 01 0f 02 01 05”というバイト列を受け渡しすれば良い事になる。
| 30 SEQUENCEを表す値。
06 後続のデータのバイト数。 02 INTEGERを表す値。
02 INTEGERを表す値。
|
| PKCS#1 | RSA公開鍵暗号システムによる暗号化処理の手順、RSA鍵のASN.1表記、三つのRSA署名アルゴリズムを定める。 |
| PKCS#3 | DH鍵交換の方法を定める。 |
| PKCS#5 | パスワードから導出された対称鍵によって暗号化を行なう方法を定める。 |
| PKCS#6 | 証明書のエクステンション部分の形式を定める。 |
| PKCS#7 | 電子署名や電子封筒(digital envelope)の形式を定める。 |
| PKCS#8 | 秘密鍵情報の形式を定める。また、秘密鍵の暗号化方法を定める。 |
| PKCS#9 | PKCS#6、#7、#8で使用される属性情報を定める。 |
| PKCS#10 | 証明書取得取得要求情報の形式を定める。 |
| PKCS#11 | ICカードなどのためのAPI仕様を定める。 |
| PKCS#12 | 機密情報の送受信のためのエンコーディング方法を定める。 |
| PKCS#13 | 楕円曲線暗号の方式を定める。 |
| PKCS#14 | 擬似乱数の生成方法を定める。 |
例として、PKCS#1で定義されているRSA秘密鍵の形式を示す。
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER -- (inverse of q) mod p }
※つまり、RSAPrivatKeyにはnとd以外にもpやqなどの付加的な情報が格納される。
証明書の規格としてはX.509という規格が主に使用されている。例として、X.509で規定されている証明書の形式を一部示す。
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING }
TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version shall be v2 or v3 subjectUniqueID
[2] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version shall be v2 or v3 extensions [3]
EXPLICIT Extensions OPTIONAL
-- If present, version shall be v3 }
※前節では、証明書は公開鍵に対する署名であると述べた。上記ASN.1表記を見ると、公開鍵(subjectPublicKeyInfo)のみに対して署名を生成するのではなく、公開鍵の所有者名(subject)、発行者名(issuer)、有効期限(validity)などさまざまな情報を合わせたもの(TBSCertificate)に対して署名を生成している事が分かる。また自己署名型証明書では、有効期限などのフィールドの改ざんを検出することができることになる。
上記の内いくつかのものはRFCとしてインターネット標準規格となっている。以下に例を挙げる。
| RFC2313 | PKCS #1 |
| RFC2314 | PKCS #10 |
| RFC2315 | PKCS #7 |
| RFC2459 | X.509 |
以下に、簡単な認証の例を示す。
・Aがシステムにログインする事を考える。
・システムは、乱数をAに送信する。
・Aは(ICカードなどに格納されている)パスワードラップされていた秘密鍵を、パスワードを入力することによりアンラップする。
・Aは、アンラップした生の秘密鍵によって、受信した乱数に対する署名を生成し、システムに送信する。
・システムは、受信した署名をAの公開鍵によって検証する。成功した場合、ログインを許可する。
上記手順では秘密の情報が送受信されることがないため、安全な認証を行なうことができる。
上記のような認証の例としては、ISO/IEC 9798がある。より高度な認証技術として、Kerberosなどが存在する。
キーリカバリは、鍵の紛失の他にも以下のような需要が存在する。
・社員が退社してしまった場合に、その社員が暗号化していた業務文書を復号化したい場合。
・法的に認められた第三者機関が犯罪捜査のために暗号文を解読したい場合。
米国は一時期後者の理由によりキーリカバリを義務づける方向を目指していた。
2. 用語と表記
| + | ワードの(2^32を法とした)加算。 |
| <<< | 左ローテートシフト。 |
| not(X) | NOT演算 |
| v | OR演算 |
| xor | XOR演算 |
| XY | AND演算 |
3. MD5アルゴリズム
bビットのメッセージを入力としてメッセージダイジェストを得る場合を説明する。ここでbは任意の非負整数。8の倍数である必要はない。各ビットを表記する際は、以下のように表記する。
m_0 m_1 ... m_{b-1}
3.1 ステップ1:パディングビットの追加
入力メッセージを、512を法として448と合同になるようにパディングする。 入力メッセージが既に448と合同である場合でもパディングは行なう。
パディングは、ビット"1"を追加し、続けて"0"を必要な分だけ追加する事によって行われる。
3.2 ステップ2:長さの追加
64ビットで表したb(パディング前のメッセージのビット長)をパディング後のメッセージの末尾に追加する。bが2^64より大きい場合は、下位64ビットを使用する(この64ビットは、二つの32bitワードとして、下位ワードが先に追加される)。
この結果メッセージ長は512ビットの倍数となる。M[0 ... N-1]を、このメッセージの各ワードとする。Nは16の倍数となる。
3.3 ステップ3:MDバッファの初期化
メッセージダイジェストの計算のために四つのワードバッファ(A, B, C, D)を使用する。各ワードは32bitレジスタである。これらのレジスタの初期値は以下の通り。(下位バイトが先に記されている)
A: 01 23 45 67
B: 89 ab cd ef
C: fe dc ba 98
D: 76 54 32 10
3.4 ステップ4:16ワードのブロック群の処理
初めに、三つの32bitワードを入力とし、一つの32ビットワードを出力とする補助関数を定義しておく。
F(X, Y, Z) = XY v not(X) Z
G(X, Y, Z) = XZ v Y not(Z)
H(X, Y, Z) = X xor Y xor Z
I(X, Y, Z) = Y xor (X v not(Z))
ちなみに、Fは「もしXならばY、そうでなければZ」を表している。
このステップでは、sin関数から作成される、64個の要素を持つテーブルT[1...64]を使用する。T[i]は、iをラジアンとしてsin(i)の絶対値の4294967296倍に等しい。
| メモ:T[i]について、適当に値を選んで定数を明示する代わりに三角関数を使用しているのは、back doorを仕組んだと疑われないようにするためである。 |
/* 各16ワードブロックを処理 */
For i = 0 to N/16-1 do
/* i番目のブロックをXへコピー */
For j = 0 to 15 do
Set X[j] to M[i*16+j]
end /* ループjの終わり */
/* A,B,C,DをAA,BB,CC,DDに退避 */
AA = A
BB = B
CC = C
DD = D
/* ラウンド1 */
/* [abcd k s i]は、a = b + ((a + F(b,c,d) + X[k] + T[i] <<<
s)を表す。 */
[ABCD 0 7 1] [DABC 1 12
2] [CDAB 2 17 3] [BCDA 3 22 4]
[ABCD 4 7 5] [DABC 5 12
6] [CDAB 6 17 7] [BCDA 7 22 8]
[ABCD 8 7 9] [DABC 9 12 10]
[CDAB 10 17 11] [BCDA 11 22 12]
[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14
17 15] [BCDA 15 22 16]
/* ラウンド2 */
/* [abcd k s i]は、a = b + ((a + G(b,c,d) + X[k] + T[i])
<<< s)を表す。 */
[ABCD 1 5 17] [DABC 6 9 18]
[CDAB 11 14 19] [BCDA 0 20 20]
[ABCD 5 5 21] [DABC 10 9 22]
[CDAB 15 14 23] [BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26]
[CDAB 3 14 27] [BCDA 8 20 28]
[ABCD 13 5 29] [DABC 2 9 30]
[CDAB 7 14 31] [BCDA 12 20 32]
/* ラウンド3 */
/* [abcd k s t]は、a = b + ((a + H(b,c,d) + X[k] + T[i])
<<< s)を表す。 */
[ABCD 5 4 33] [DABC 8 11 34]
[CDAB 11 16 35] [BCDA 14 23 36]
[ABCD 1 4 37] [DABC 4 11 38]
[CDAB 7 16 39] [BCDA 10 23 40]
[ABCD 13 4 41] [DABC 0 11 42] [CDAB
3 16 43] [BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [CDAB
15 16 47] [BCDA 2 23 48]
/* ラウンド4 */
/* [abcd k s t]は、a = b + ((a + I(b,c,d) + X[k] + T[i] <<<
s)を表す。 */
[ABCD 0 6 49] [DABC 7 10 50]
[CDAB 14 15 51] [BCDA 5 21 52]
[ABCD 12 6 53] [DABC 3 10 54] [CDAB
10 15 55] [BCDA 1 21 56]
[ABCD 8 6 57] [DABC 15 10 58] [CDAB
6 15 59] [BCDA 13 21 60]
[ABCD 4 6 61] [DABC 11 10 62] [CDAB
2 15 63] [BCDA 9 21 64]
/* 得られた結果と退避しておいた値を足しあわせる */
A = A + AA
B = B + BB
C = C + CC
D = D + DD
end /* ループiの終わり */
3.5 ステップ5:出力
A,B,C,Dを出力する。Aが下位バイト、Dが上位バイトである。