本記事は 暗号学一人アドベントカレンダー 第2日目の記事です。風邪引いて投稿遅れてますが今週終わりにはキャッチアップします…><
今回の内容はお仕事で暗号を使う必要が出てきたときにこのへんは抑えておいて、という内容です。とはいえそもそもあんまり使う分野ではないのでこれだけ知っておくだけでもちょっとは差がつく…のかな?
大前提その1: 暗号アルゴリズムを自前実装してはいけない
暗号の本を読んだからとりあえずオレオレ暗号方式が作れる!っていうのは絶対に嘘です。というか大抵の暗号の本にはちゃんとこういう注意が書いてあると思います。かつて長らく標準の暗号方式として使われていたDESですら「線形にならないように気をつけて設計したハズ」なのに「特定のs-blockに微妙に線形性っぽい挙動が見られる」せいで効率のいい解読方法が編み出された、みたいなことがあるくらい、暗号アルゴリズムの設計は非常に繊細な技術を要求されます。弊社独自の暗号化方式だから安全みたいにいうのは絶対に地雷です。逃げましょう。
このようなSecurity by Obscurity(アーキテクチャなどの秘匿性をセキュリティの根拠に置くこと)を否定する原則としてケルクホフスの原理というのがあります。クロード・シャノンによる言い換えでは「敵はシステムを知っている」と表現されていて、例えていうならば「暗号機そのものが敵の手に落ちて解析されたとしても安全である必要がある」ということを言っています。
大前提その2: 暗号アルゴリズムが公開のやつでも自前実装したものをproductionで使ってはいけない
おとなしくライブラリを使ってください。これは、公開されている標準アルゴリズムが多数の目の検証を経ているように、オープンソースの暗号ライブラリは多数の研究者やハッカーに攻撃を試みられています。OS標準で使われるOpenSSLよりもセキュアなライブラリを実装できる自信がありますか?であればお願いなのでオープンソースの暗号ライブラリにコミットしてください。
規格どおりに実装したのに何でセキュアじゃないものができてしまうかというと、例えばGCの制御が中途半端でメモリの中間状態が漏洩してしまうケースだったり、復号に成功する場合としない場合とで微妙に実行時間が違うようなケースだったりで、アルゴリズムの入出力としては正しいけれど情報を漏らしてしまうようなケース(サイドチャネル攻撃といいます)が存在します。サイドチャネル攻撃から適切に実装を保護するのは非常に難易度の高い技術です。
この項目は特許の関係からオープンソース使うことができない場合はあてはまりませんが、がんばってください、としか言えないですね…。
言語組み込みの暗号APIがプリミティブな操作しか提供していない場合は避けたほうがいい場合がある
そのうえで、可能であれば「エンドユーザーにとって使いやすい暗号APIが提供されていて」「信頼のおける発行者によるもの、あるいは検証がされているもの」であるライブラリを使ったほうがよいです。後の項目でも説明しますが、暗号アルゴリズムの選択まではうまくいったとしてもパラメータの誤用によってセキュリティが保たれなくなるケースが存在します。なので、「平文と鍵を入れるだけで暗号化してくれるAPI」くらいの簡便性があるAPIまでラッピングしてくれたものを使ったほうが暗号を深く知りたくない人にはよいです。
そのうえで、どのアルゴリズムを選べばよいか
- ハッシュアルゴリズム(パスワードストアなどで使う): SHA-2(SHA256, SHA512)、可能ならばSHA-3(Keccak)
- 対称鍵暗号:AES、暗号利用モードはCTRモードもしくはGCMモード
- DES, Triple-DESは(少々)効率のいい解読法が存在することに加え、鍵長の長さから原理的に安全性が落ちます
- なお、どの暗号利用モードでも初期化ベクトルの使い回しは厳禁
- 公開鍵暗号:そもそも自分で暗号方式を選択することは割と稀といえば稀
- RSA暗号の鍵長2048bitが一般的
- 署名検証にECDSA(楕円曲線DSA)が使われることもある。対応してる環境ならば鍵長が短くて済むので性質がよい
- 同様に、素のDiffie-Hellmanの代わりにECDHのほうがよく見るようになってきている
次回はHistorical Cryptoの予定でしたがセキュリティ定義から入る予定です。