[解決済み] Java 256ビットAESパスワードベース暗号化機能
質問
私は256ビットのAES暗号化を実装する必要がありますが、私がオンラインで見つけたすべての例は256ビットのキーを生成するために"KeyGenerator"を使用していますが、私は私自身のパスキーを使用したいと思います。どうすれば独自のキーを作成できますか?256ビットにパディングしてみましたが、キーが長すぎるというエラーが出ます。無制限管轄パッチはインストールしてあるので、問題ないのですが :)
Ie. KeyGeneratorはこんな感じです.
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
EDIT
実は、パスワードをビットではなく256バイトにパディングしていたのですが、これでは長すぎました。以下は、この件に関してもう少し経験を積んだので、私が使っているコードです。
byte[] key = null; // TODO
byte[] input = null; // TODO
byte[] output = null;
SecretKeySpec keySpec = null;
keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(input)
自分でやらなければならないこと:-)
解決方法は?
を共有します。
password
(a
char[]
) と
salt
(a
byte[]
で選択された-8バイト
SecureRandom
は、帯域外の受信者と良い塩(秘密にしておく必要はない)を作ることができます。そして、この情報から良い鍵を導き出す。
/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
65536と256というマジックナンバー(どこかで定数として定義されている可能性があります)は、それぞれ鍵の導出反復回数と鍵のサイズです。
鍵の導出関数を反復させることで、多大な計算量を必要とし、攻撃者が多くの異なるパスワードを素早く試すことを防いでいる。この繰り返し回数は、利用可能な計算機資源に応じて変更することができる。
鍵のサイズは128ビットまで小さくすることができ、これはまだ強力な暗号化と考えられているが、AESを弱める攻撃が発見された場合の安全マージンはあまりない。
適切なブロックチェーンモードで使用すると、同じ派生鍵を使用して多くのメッセージを暗号化することができます。その際 暗号ブロック連鎖(CBC) このため、平文が同一であっても、異なる暗号文が生成されます。CBCは最も安全な方式ではないかもしれません(下記のAEADを参照)。異なるセキュリティ特性を持つ他の方式も数多くありますが、いずれも同様のランダムな入力を使用します。いずれにせよ、各暗号化操作の出力は、暗号文 と 初期化ベクトル
/* Encrypt the message. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes(StandardCharsets.UTF_8));
を格納します。
ciphertext
と
iv
. 復号化する際には
SecretKey
は全く同じ方法で再生成され、パスワードと同じソルトと反復パラメータを使用します。この鍵で暗号を初期化する。
と
メッセージと一緒に保存された初期化ベクトル。
/* Decrypt the message, given derived key and initialization vector. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
String plaintext = new String(cipher.doFinal(ciphertext), StandardCharsets.UTF_8);
System.out.println(plaintext);
Java 7搭載API AEAD暗号モード対応 OpenJDKやOracleディストリビューションに含まれるSunJCEプロバイダは、Java 8からこれらを実装しています。CBCの代わりに、これらのモードの1つを強くお勧めします。
A
java.security.InvalidKeyException
というメッセージが表示された場合、暗号強度が低いことを意味します。
は
無制限強度管轄のポリシーファイルが正しい場所にない。JDKでは、これらのファイルは
${jdk}/jre/lib/security
問題の説明からすると、ポリシーファイルが正しくインストールされていないようです。システムには複数のJavaランタイムが存在する可能性があります。正しい場所が使用されていることを再確認してください。
関連
-
Java エラー報告 スレッド "main" での例外 java.util.NoSuchElementException
-
java.util.NoSuchElementException 原因解析と解決方法
-
スタイルシートとして解釈されるリソースが、MIMEタイプtext/htmlで転送される。
-
エラーが報告されました。リソースの読み込みに失敗しました:サーバーは500(内部サーバーエラー)のステータスで応答しました。
-
アクセス制限について アプリケーションの種類がAPIでない(必要なライブラリの制限)。
-
Methodのinvokeメソッド実装のJavaリフレクション
-
Java コンパイルエラー - スレッド "main" で例外 java.lang.Error: 未解決のコンパイル問題です。
-
あるコードに出会いましたが、何に使うのか理解できません。 List<String> list = new ArrayList<String>() { { a
-
Google Chromeのエラー「Not allowed to load local resource」の解決策について
-
[解決済み] AES暗号化モード(CBC ECB CTR OCB CFB)の選択方法は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
エラーが報告されました。リソースの読み込みに失敗しました:サーバーは500(内部サーバーエラー)のステータスで応答しました。
-
この行に複数のマーカーがある - HttpServletResponseが型エラーに解決できない
-
スレッド "main" で例外発生 java.lang.ArrayIndexOutOfBoundsException: 4 at text.Division.main(Divisi
-
Spring BootのテストメソッドFailed to load ApplicationContextの問題を解決する
-
javaでクラスを作成すると、enclosing classでないように見える
-
スレッド "main" で例外発生 java.net.BindException: アドレスは既に使用中です。NET_Bind
-
SocketTimeoutExceptionです。読み込みがタイムアウトしました
-
Exception: java.util.NoSuchElementException: 行が見つかりません
-
java -serverコマンドで「Error: no `server' JVM at ... jvm.dll」を解決する方法です。
-
コミットには何も追加されないが、未追跡のファイルが存在し、gitで未追跡のファイルに対する完璧な解決策