■ はじめに
SSL通信では、以下「SSLシーケンス概要」の★部分にあるように乱数を作成してやり取りする。 今回は、Javaでの実装でこの乱数作成について考える # 本当は、以下のトラブルを解決する過程で、SecureRandom クラスを学ばなければならなかったので # トラブルシューティングの前段階として、知識を纏めてみた
SSLシーケンス概要
http://itpro.nikkeibp.co.jp/article/COLUMN/20060731/244715/?rt=nocntより Client Server | | | httpsでサーバに対してリクエストを出す | |----------------------------------------->| | | | サーバ証明書を送付 | |<-----------------------------------------| 証明書をチェック | | | | ★乱数作成★ | | | | サーバ証明書の | | 公開鍵で乱数を暗号化 | | | | | 暗号化した乱数を送信 | |----------------------------------------->| 乱数を元に共通鍵を作成 | | 乱数を元に共通鍵を作成 | | | 共通暗号鍵方式でデータを暗号化して通信 | |<---------------------------------------->| | |もう少し詳細なシーケンス図は以下の関連記事を参照のこと
http://blogs.yahoo.co.jp/dk521123/34090545.html
■ 暗号用乱数生成方法
[1] SecureRandom.getInstanceStrong() で作成する(From Java1.8) => プラットフォームでもっとも強力なアルゴリズムを使用してSecureRandomインスタンスを作成 [2] SecureRandom.getInstance(【アルゴリズム】)で作成する => 【アルゴリズム】:"NativePRNGBlocking"/"NativePRNGNonBlocking"/"NativePRNG"/"SHA1PRNG" など => OSによって、サポートするアルゴリズムに差異があるので注意https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/SunProviders.html#SecureRandomImp
[3] new SecureRandom()で作成する [4] 「-Dsecurerandom.source=file:/dev/urandom」or 「System.setProperty("securerandom.source", "file:/dev/urandom");」 => 「securerandom.source=file:/dev/random」だと「/dev/random」の性質上、ブロックする可能性があるので注意http://otndnld.oracle.co.jp/document/products/E13153_01/wlcp/wlss40/configwlss/jvmrand.html
http://qa.atmarkit.co.jp/q/1901
どの方法がいい?
ずるい結論かもしれないが、結局は...* 開発環境だけでなく、本番を想定した環境で試したうえで決める => 一見、「SecureRandom.getInstanceStrong()を指定しとけばいい」って思ったが、 ハードウェア(PC/Mobile/Raspberry PI etc...)・OS環境・使用する証明書・暗号アルゴリズムなどによっては、 パフォーマンスに影響するので、しっかり実環境で試した方がいい
選定の仕方
i) まず、Java1.8以上であれば「[1] SecureRandom.getInstanceStrong()」を使って、実環境で確認する => 特に問題がなければ、OK! => (実際に起こった現象なのだが)SecureRandom.getInstanceStrong()を使用して 以下の関連記事のようなトラブルがあり、リクエストタイムアウトでSSL通信できなかった。 (必ずしも、SecureRandom.getInstanceStrong()を使えば正解って訳じゃない)http://blogs.yahoo.co.jp/dk521123/36643583.html
ii) i)で問題がある又はJava1.7以下の環境の場合は、 「[2] SecureRandom.getInstance(【アルゴリズム】)」で直接アルゴリズムを指定するか 「[3] new SecureRandom()」を使用し、実環境で確認する ※ 以下のサイトが非常に参考になるhttp://qiita.com/aibax/items/29e09318ac85c4e93c1a
参考文献
Oracleドキュメント
API「SecureRandom」仕様https://docs.oracle.com/javase/jp/8/docs/api/java/security/SecureRandom.html
OSで使用できるアルゴリズムと優先順位の一覧
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/SunProviders.html#SecureRandomImp
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/SunProviders.html#SunPKCS11Provider
乱数生成に伴う JVM の遅延の回避
http://otndnld.oracle.co.jp/document/products/E13153_01/wlcp/wlss40/configwlss/jvmrand.html
「/dev/random」「/dev/urandom」
http://piyopiyocs.blog115.fc2.com/blog-entry-665.htmlhttp://myokota.hatenablog.jp/entry/2015/01/25/214528
その他サイト
http://blog.64p.org/entry/2014/10/08/233604http://qiita.com/aibax/items/29e09318ac85c4e93c1a
http://megalodon.jp/2014-1009-0140-17/blog.64p.org/entry/2014/10/08/233604
https://gist.github.com/buzztaiki/ca89a079b093d716ef94