2013-08-14 21 views
41

標準のJDKを使用して、Javaで安全なランダムAESキーを生成するための推奨される方法は何ですか?他の記事でJavaで安全なランダムAESキーを作成する方法は?

、私はこれを発見したが、SecretKeyFactoryを使用することは良いアイデアかもしれません:

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
SecureRandom random = new SecureRandom(); // cryptograph. secure random 
keyGen.init(random); 
SecretKey secretKey = keyGen.generateKey(); 

答えは、それが生成する良い方法である理由の説明が含まれている場合それは素晴らしいことですランダムキー。ありがとう!

+0

とランドを置き換えるこのmighthヘルプhttp://stackoverflow.com/questions/10252449/is-aes-key-random – Tala

+0

@Talaこれは、[引用されたコード]を見つけた場所です(http://stackoverflow.com/a/10252662/1005481)。しかし、その投稿から、私はランダムキーを作成する方法とそれがなぜ安全な方法であるかについてのコンセンサスを決定することができませんでした。 –

答えて

53

私はあなたの提案のコードを使用していますが、若干の簡素化となります

KeyGenerator keyGen = KeyGenerator.getInstance("AES"); 
keyGen.init(256); // for example 
SecretKey secretKey = keyGen.generateKey(); 

プロバイダは、それがランダム性を得ることを計画方法を選択してみましょう - どのようなプロバイダとして良いではないかもしれない何かを定義していませんすでに選択されています。

このコード例では、java.securityファイルを構成して、優先プロバイダをリストの先頭に含めることを前提としています(as Maarten points out below)。プロバイダーを手動で指定する場合は、KeyGenerator.getInstance("AES", "providerName");に電話するだけです。

真に安全な鍵を作成するには、鍵を生成して保護するためにhardware security module(HSM)を使用する必要があります。 HSM製造業者は、通常、上記のコードを使用して、すべてのキー生成を行うJCEプロバイダを提供します。

+1

通常、私はプロバイダ名も省略します。プラットフォームを設定する(例えば、 'java.security'ファイルを使うか、' Security.addProvider() 'と同様にしてプログラムで' Provider'を設定します)。さもなければ、コードは移植性が低くなり、ユーザは例えば、アプリケーションコードを変更することなくHSMを実行できます。 –

+0

プロバイダを指定する必要があるのはなぜですか?デフォルトの動作では、アルゴリズムをサポートする最も優先度の高いインストールされたプロバイダを使用します。これは十分です。 –

+2

すべての鍵生成メソッドが等しく作成されるわけではなく、たとえば、明示的に選択する必要があります。プロバイダの鍵生成方法これは特に、セキュリティトークンのプロバイダに使用されます。ただし、AESの場合、乱数ジェネレータの方が重要な場合があります。たとえば、デフォルトよりも遅く安全なFIPS認証乱数ジェネレータを使用したい場合があります。 –

19

KeyGeneratorを使用するのが好ましい方法です。ダンカンが指摘したように、私は初期化中にキーサイズを確かに与えるでしょう。 KeyFactoryは、既存のキーに使用する方法です。

OKだから、これは根性に欠けます。原則として、AESキーは任意の値を持つことができます。 (3)DESのように「弱い鍵」はありません。 (3)DESパリティビットのように特定の意味を持つビットもありません。したがって、キーの生成は、ランダムな値を持つバイト配列を生成し、その周囲にSecretKeySpecを作成するのと同じくらい簡単です。

しかし、使用している方法にはまだ利点があります。具体的には、KeyGeneratorがキーを生成するために作成されています。これは、この世代のためにコードを最適化できることを意味します。このにはに効率性とセキュリティ上の利点があります。たとえば、キーを公開するタイミング・サイド・チャネル攻撃を回避するようにプログラムすることができます。重要な情報を保持しているbyte[]をクリアすることは、既にスワップファイルに漏洩している可能性があるので、あらかじめ解読することをお勧めします(これはとにかく可能性があります)。

さらに、すべてのアルゴリズムが完全ランダムキーを使用しているわけではありません。したがって、KeyGeneratorを使用すると、他のアルゴリズムに簡単に切り替えることができます。より現代的な暗号は完全にランダムな鍵だけを受け入れます。これは、例えば、 DES。

最後に、私の場合、最も重要な理由は、KeyGeneratorメソッドが、安全なトークン(スマートカード、TPM、USBトークンまたはHSM)内のAESキーを処理する唯一の有効な方法だということです。 でbyte[]を作成した場合、のキーはでなければなりません。つまり、鍵は安全なトークンに入れられるかもしれませんが、鍵はメモリに関係なく公開されます。通常、セキュアトークンは、セキュアトークンで生成されるか、例えば、スマートカードまたはキー式である。 KeyGeneratorは、鍵がセキュアトークン内で直接生成されるようにプロバイダに提供することができます。

Duncan's answerに示されているとおり、常にキーサイズ(および他のパラメータ)を明示的に指定します。 になると、アプリケーションの動作が不明確になり、各プロバイダに独自のデフォルトが設定される可能性があるため、プロバイダのデフォルトに頼らないでください。

+0

この優れた背景情報をありがとう! –

+0

もっとメリハリ。いつものようにすばらしい答え:-) –

2

他の投稿に多くのアドバイスがあります。これは私が使用するものです。

Key key; 
SecureRandom rand = new SecureRandom(); 
KeyGenerator generator = KeyGenerator.getInstance("AES"); 
generator.init(256, rand); 
key = generator.generateKey(); 

あなたは私がいつかテスト目的のために行う別のランダム性プロバイダを、必要な場合は、単に

MySecureRandom rand = new MySecureRandom(); 
+0

初めて乱数ジェネレータを指定すると、2回目のAESキーの長さ(256)が使用されます。これらは個別のinitメソッドです。 – Andy

関連する問題