暗号化とハッシュ化に関する基本的な事柄まとめ


本記事は拙ブログ記事「[暗号化とハッシュ化に関する基本的な事柄まとめ - the world as code](http://chroju.github.io/blog/2015/07/20/encryption-hash-at-first/)」のリファイン版です。

* 暗号化とハッシュ化は違う。暗号化はデータの秘匿を目的としており、適切な鍵を用いることで復号が可能。ハッシュ化はデータの置換がそもそもの目的であり、ハッシュ関数により一定のフォーマットへ不可逆の変換を行う。
* ただし、衝突耐性を持つことなどにより、セキュリティ用途に適する「暗号学的ハッシュ関数」というものもあるらしい。デジタル署名やメッセージ認証符号への使用を目的とされており、逆にチェックサム等に使用するには計算が「重い」。

暗号
==================================================

## アルゴリズム

### RSA
* 公開鍵暗号。素因数分解の計算難度を根拠としたもの。なおRSAは発明者の名前から取られたものであり、何かの略ではない。
* SSHログイン時の鍵認証やSSL認証など、広く使われる。
* 秘密鍵生成コマンドとして`openssl genrsa`がある。SSH鍵認証では`ssh-keygen`を用いる。

### DSA
* Digital Signature Algorithm
* 公開鍵暗号。根拠は離散対数問題の困難性。
* SSH2が出た頃、特許が云々の関係でRSAの使用が推奨されなくなり、こっちが使われたりしたらしい。今は解消しているので、改めてRSAが推奨されている。
* `ssh-keygen`の暗号化方式に指定することも可能だが、特に理由がなければ、あえてDSAを使う必要はなさそう。
* 楕円曲線を用いたECDSAという変種がある。楕円曲線暗号はより短い鍵長で高い強度が保てるので、ポストRSAとして注目される。（[@ITの技術解説](http://www.atmarkit.co.jp/ait/articles/1507/28/news002.html)を読んだがよくわからない）。ただしMacの標準SSH等、ECDSAに対応していない環境もまだ多いので注意が必要。

### DES
* Data Encryption Standard
* 共通鍵暗号。鍵長56bitのブロック暗号。
* 鍵長が短すぎるため、現在では安全ではないとされるが、暗号化復号化処理を3回実行するトリプルDESという形で実用されている。
* `openssl genrsa`での秘密鍵生成時に、パスフレーズによるトリプルDESでの暗号化を施すため、`-des3`オプションが用いられる。

### AES
* Advanced Encryption Standard
* 共通鍵暗号。DESの安全性低下に伴い開発された、鍵長128bit超のブロック暗号。
* zipやrarの暗号化等で用いられている。

## xx bitってなに？
暗号化に用いる暗号鍵の桁数（鍵長）を示す。同じアルゴリズムを用いても鍵が異なれば暗号化結果は変化する。従って鍵を特定されなければ情報漏洩の問題はない。鍵長が長ければ長いほどパターンの数も増えるため、強度は増すことになる。

## 暗号強度の2010年問題
* コンピューターの計算処理性能の向上に伴い、暗号強度は相対的に下がっていく。このため2010年をもって、アメリカ政府では1024bit以下のRSA、DSA暗号、160bit以下のECDSA、また2TDESとSHA-1の使用を廃止している。
* 最新の`ssh-keygen`は[デフォルトの鍵生成がRSAの2048bit](http://euske.github.io/openssh-jman/ssh-keygen.html)になっているので、特に気にする必要はないが、念押しするのであれば`ssh-keygen -t rsa -b 2048`と指定できる。


ハッシュ
==================================================

## ソルト
ハッシュ化前に対象文字列に付加するランダムな文字列。同一文字列のハッシュ化時に衝突が防げる、レインボーテーブルによる探索に対する妨害になる、といった利点がある。`openssl passwd`コマンドでは、`-salt stirng`オプションを用いることで、`string`をソルトとしたパスワードのハッシュ化ができる。

## ストレッチング
ハッシュ化を何重にも実施することで、攻撃を受けた場合の解析に必要な時間を長期化して時間を稼ぐ策。当然ながらハッシュ化も長期化、高負荷化するのでほどほどに。

## フィンガープリント
SSH初回ログインで表示されるやつ。接続先サーバーに保存されている公開鍵`etc/ssh/ssh_host_rsa_key.pub`のハッシュ値。クライアント側では、一度接続したサーバーのフィンガープリントが`~/.ssh/known_hosts`に記述され、次回以降のログインで照合が行われる。変更があると、同一ホスト名もしくはIPを用いたサーバーなりすましの危険性もあるため、警告が表示される。`ssh-keygen -lf`で先の公開鍵を確認することにより、フィンガープリントの表示が可能。

## アルゴリズム

### md5
* Message Digest Algorythm 5
* 出力128bitのハッシュアルゴリズム。ファイル配布時のチェックサムなどに用いられる。
* 安全性は高くないことが判明しているため、日米ともにSHAの使用が推奨されている。
* コマンドは`md5sum`あるいは`openssl md5`を使用する。
* なおパスワードハッシュ化でよく用いられる`openssl passwd`はmd5による実装。

### sha
* Secure Hash Algorithm。暗号学的ハッシュ関数の一つ。
* SSL、SSH等で用いられる暗号化アルゴリズム。
* SHA-0,1,2,3が存在しており、SHA-1には脆弱性が存在するため、SSL証明書はSHA-2への全面移行が推奨されている。すでにGoogle ChromeではSHA-1による証明書に対して警告が表示される。
* SHA-2は鍵長によりSHA-224、SHA-256、SHA-384、SHA-512といったバリエーションが存在する。
* 上述の通り`openssl passwd`はSHA非対応だが、`grub-crypt`がSHA-2によるハッシュ化に使える模様。
  参考: [CentOS6.5でランダムSalt付きSHA-512のシャドウパスワードを生成する - ひろうぃんの雑記](http://heroween.hateblo.jp/entry/2014/07/28/133713)

## ハッシュ化コマンドは何を使う？

インフラエンジニアとして、ハッシュ化を用いる機会が最も多いのはChef等のプロビジョニングツールでユーザーのパスワードを指定する場合なのだが、これをシェルコマンドで実行しようとすると`openssl passwd`によるmd5ハッシュ化ぐらいしか手段がない。上述の通りmd5の安全性は高くないため、個人的には使用が躊躇われるところではあるのだが、世のChefハウツー記事等を見ているとだいたいがmd5 + saltでのハッシュ化で済ませている。いいのかな？

有効と思われる代替手段の一つに`grub-crypt`コマンドがあり、これはSHA-256とSHA-512に対応しているが、GRUB Legacyのツールであるため、最近のサーバーだと導入されていないことが多い。なおGRUB2では`grub2-mkpasswd-pbkdf2`コマンドが後継となっているようだが、これはPBKDF2という鍵導出関数？によるハッシュ化を行うとのことで、ちょっと理解が追い付いていない。

他の手段としてはRuby、Perl、Python等のLLを使うというものがある。ワンライナーで書けるので、`grub-crypt`の使えない環境ならこれが一番スマートかもしれない。
  
### 参考
* [sha512でハッシュされたsaltつきパスワードを生成するには | Nobwak's Lair](http://april.fool.jp/blogs/2013/09/sha512%E3%81%A7%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E3%81%95%E3%82%8C%E3%81%9Fsalt%E3%81%A4%E3%81%8D%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B%E3%81%AB/)