セキュリティ技術入門

4つのセキュリティ技術(ハッシュ関数、乱数、共通鍵暗号、公開鍵暗号)について説明します。


核となる4つのセキュリティ技術

これらを実装したコードは組み合わさって様々なところ(オープンソース・プロトコル等)で多用されている。コマンドでも比較的簡単に操作できるようになっている。


ハッシュ関数

ハッシュ関数は、ファイルやデータの完全性(本物か?壊れてないか?)を検証するためによく用いられている。

ハッシュ関数の仕組み

  1. 関数なので、入力値(入力データ・ファイル)から出力値(ハッシュ値)が計算される。
  2. 同じ入力値からは、必ず100%絶対同じ出力値となる。
  3. 出力値は例えば32文字などと短くなるように作られている。(入力は無限種類、出力は有限)
  4. 出力値が同じになったなら、入力値が同じなのだと判断する。
  5. 関数に欠陥がなければ、この判断が間違っている可能性はほぼゼロ。

ハッシュ関数はいくつも種類があり(数学者の競争)、弱い順に例をあげるとMD5、SHA-1、SHA-256など。

MD5はハッシュ値が32文字(数字とa~fの計16種類×32桁)であり、入力値が異なるのにハッシュ値が同一になる確率は、「コインを128回投げたら全部表が出る」のと同じ。

ハッシュ関数の利用例

OSS(オープンソースソフト)の公式サイトなどでは、プログラム本体のダウンロードページにハッシュ値の案内があることが多い。そのハッシュ値と、ダウンロードしたファイルに対して自身で出したハッシュ値(下記コマンド)とを比べて、一致していれば「本物、壊れていない、悪の組織がウィルスをこっそり組み込んだりしてない」と判断する。

# MD5の場合
md5sum ダウンロードファイル

乱数

乱数は、暗号作成やゲームなどランダムな結果を出すために利用されている。

乱数が最強の暗号になる仕組み

コンピュータで扱う文字列などすべてのデータは、内部では0と1で表現(符号化/エンコード)されている。この0と1の意味のある並びは、次の手順で意味のない(ランダムな)0と1の並び(完全完璧な暗号)になる。

  1. 平文: 元の意味のある0と1の並びは、仮に以下のとおりとする。(意味が見えるように、途中でわざと0や1を反復させた)

  2. : ランダムな0と1の並びを平文と同じ長さで作成する。

  3. 暗号文: 平文と鍵との排他的論理和を求める。(両者の同じ桁をみて、片方だけ1なら1、それ以外なら0と計算する)

  4. 復号: 暗号文と鍵との排他的論理和を求める。これで元の平文になった。

ポイントは、鍵がランダムならば、排他的論理和によって暗号文も必ずランダムになること。鍵を知らない者は、原理的に、無限の時間をかけても、絶対に100%絶対に平文がわからない。

ゲームなどでランダムな結果を出す例

ゲームに限らないが、プログラミングではランダムを利用することは多い。例として、shufコマンドは指定した配列をランダムに返す。

# 「あいうえお」からランダムに出力
shuf -e あ い う え お
あ
お
う
い
え

共通鍵暗号

共通鍵暗号は、暗号化に使う鍵と復号に使う鍵が同じ方式の暗号のこと。その具体的な暗号化手順(アルゴリズム)はいくつもある。

共通鍵は(表面的には)パスフレーズのことなので、強いパスフレーズにして第三者に漏れないようにする。

opensslで暗号化

例として、opensslコマンドで共通鍵暗号を使ってみる。ここではcamellia256というアルゴリズムを使っている。

# -eは暗号化
openssl enc -e -camellia256 -in 平文ファイル -out 暗号文ファイル

opensslで復号

# -dは復号
openssl enc -d -camellia256 -in 暗号文ファイル -out 復号ファイル

公開鍵暗号

公開鍵暗号は、暗号化の鍵と復号の鍵が別になっていて、作成者だけの秘密にするプライベート鍵をもとに、世界に公開する公開鍵を作る方式の暗号のこと。逆に公開鍵からはプライベート鍵を作ることはできない(宇宙年齢費やすほど困難)。両者の組み合わせを鍵ペアという。

アルゴリズムはRSA楕円曲線暗号などがある。

プライベート鍵は、(表面的には)プライベート鍵ファイルのことなので、それを強いパスフレーズで守りつつ(暗号化)、第三者に漏れないようにする。

公開鍵は、コマンド一つで世界中にある鍵サーバに公開でき、他人のも入手もできる。

公開鍵暗号の仕組み

20世紀後半まで暗号といえば共通鍵暗号だったが、鍵を通信相手に渡す過程で第三者に傍受されるリスクがあった(鍵配送問題)。公開鍵暗号では第三者に見られてもいい公開鍵で暗号化し、それは公開鍵では復号できないから鍵配送問題が生じず、暗号文はプライベート鍵の作者のみが復号できる。

数学的な仕組みの例

「プライベート鍵→公開鍵」という一方向の流れでのみ作成できる仕組みは、数学の一方向性関数を利用している。例として、「素数P × 素数Q = N」における、「NからPとQを逆算するのは困難」という性質。Nは公開鍵、PとQはプライベート鍵に当たる。

公開鍵暗号の利用例

gpgコマンドで暗号化から復号までの流れ

公開鍵で暗号化したらペアとなっているプライベート鍵でしか複号できない。

  1. 鍵ペアを作成(暗号文の受取人)

    gpg --gen-key
  2. 鍵サーバへ公開鍵を流す(暗号文の受取人)

    gpg --send-keys 鍵ID
  3. 鍵サーバから公開鍵を取得(暗号文を送る人)

    gpg --recv-keys 鍵ID
  4. 手元にある公開鍵のリスト

    gpg --list-keys
  5. 受取人の公開鍵で暗号化(暗号文を送る人)

    gpg --recipient 暗号文の受取人 --armor --encrypt 平文ファイル

    できた暗号文を送って、

  6. 復号(暗号文の受取人)

    gpg 暗号文ファイル

gpgコマンドで電子署名して署名検証するまでの流れ

電子書名の仕組み

プライベート鍵で暗号化したら、ペアとなっている公開鍵でしか復号できない。言い方を変えれば、公開鍵で復号できたファイルは、プライベート鍵の保有者が作った本物とわかる。これが「私が作った本物」と証明する電子署名の仕組み。

  1. 鍵ペアを作成(電子署名する人)

    gpg --gen-key
  2. 鍵サーバへ公開鍵を流す(電子署名する人)

    gpg --send-keys 鍵ID
  3. 電子署名する(分離署名の例)

    gpg --local-user 電子署名する人 --detach-sign --armor 署名するファイル本体

    本体のファイルとできた分離署名ファイルを送って、

  4. 鍵サーバから公開鍵を取得(署名検証する人)

    gpg --recv-keys 鍵ID
  5. 手元にある公開鍵のリスト

    gpg --list-keys
  6. 署名検証

    gpg --verify 分離署名ファイル 本体ファイル