3

BouncyCastle を使用して、CBC モードで AES および PKCS5 パディングを使用して一部のファイルを暗号化/復号化しています。

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");

今2つの質問:

  • データを復号化するために提供されたキーが正しいかどうかを確認するにはどうすればよいですか?
  • 暗号化された入力が変更されていない (たとえば、ユーザーが HEX エディターを使用して変更していない) ことを確認するにはどうすればよいですか?

ありがとう

4

5 に答える 5

4

CBC の代わりに、CCM や GCM などのAEAD モードを使用できます。これらのモードは暗号化されたメッセージを認証するため、間違ったキーが使用されているか、暗号テキストが変更されている場合は、それを検出できます。ただし、これらのケースを区別することはできません。

Java 7 の暗号化 API では GCM がサポートされていますが、Oracle の Java 実装に同梱されている SunJCE プロバイダーはまだサポートしていません。BouncyCastle などのサードパーティ プロバイダーを通じてサポートを受けることができます。

デジタル署名やメッセージ認証コードなどの追加の暗号化サービスを使用すると、同じことを実現できます。

于 2012-08-31T22:33:35.150 に答える
1

暗号化は、アルゴリズムと暗号化キーだけでなく、システム構成にも大きく関係しています。

一般に、キーが正しいかどうかを判断することはできません。復号化されるはずのデータを復号化するために任意のキーを使用できますが、それが「正しい」結果であるかどうかを判断するのは、他のメカニズム次第です。

一般に、暗号化を解除するデータが変更されていないかどうかは、何らかの外部チェック以外では判断できません。暗号化されたデータのいずれかを変更すると、復号化された出力が大幅に変更され、おそらくゴミとして解釈されるものになるというのは、ほとんどの暗号化システムの特性です。

于 2012-08-31T22:28:07.053 に答える
1

BC 暗号化に関するこのチュートリアル、具体的には InitCiphers メソッドを見て、実際の暗号の種類を指定する 2 番目のコード ブロックを詳しく見てください。

データを復号化するために提供されたキーが正しいかどうかを確認するにはどうすればよいですか?

JCE Javadocsによると、具体的にはClass SecretKeySpecのコンストラクター:

このコンストラクターは、指定されたバイトが指定されたアルゴリズムの秘密鍵を実際に指定しているかどうかをチェックしません。たとえば、アルゴリズムが DES の場合、このコンストラクターはキーの長さが 8 バイトであるかどうかをチェックせず、弱い鍵または準弱い鍵もチェックしません。これらのチェックを実行するには、アルゴリズム固有の鍵仕様クラス (この場合は DESKeySpec) を使用する必要があります。

インターフェース KeySpecは、基本的には検証オプションのリストである、すべての実装クラスをリストすることに注意してください。

暗号化された入力が変更されていない (たとえば、ユーザーが HEX エディターを使用して変更していない) ことを確認するにはどうすればよいですか?

それはそう。それは良いことです。「入力」はかなり一般的です。復号化する実際のコンテンツを意味しますか? まあ、改ざんされた場合、適切に復号化されないと思います。それは理にかなっていますか?

Bouncy Castle FAQの項目 (6) で説明されているように、パリティ ビットが変更されたキーの場合について話している場合は、キーに対して実際のパリティ チェックを行う必要があります。キーの最初の 56 バイトのみが暗号化演算に使用され、最後の 8 バイトはパリティ チェック用に予約されています。したがって、基本的に、「キー」の最後の部分は変更でき、最初の部分は引き続き使用できます。パリティまたはキーが変更されたかどうかを検出するには、パリティ チェックを実行します。パリティチェックを行うと、この小さな問題が見つかりました。また、これらのキーでパリティが設定される方法の詳細については、Jan Luehe による Class DESKeyGenerator の JDK7 Crypto Provider ソースのコメントを参照してください。(一番下) パリティ設定について説明します。

私は最近 BC とやり取りをしました。この情報が役に立てば幸いです。

于 2012-09-01T09:49:58.603 に答える
1

最初にメッセージの完全性を検証する MAC を追加してから、メッセージを復号化する必要があります。MAC の一般的な選択肢は、SHA-2 など、任意のハッシュ関数を使用した HMAC です。

これを自分で行う代わりに、認証された暗号を使用することをお勧めします。AES-GCMが一般的な選択肢です。ただし、その場合、IV を再利用しないように十分に注意する必要があります。

于 2012-08-31T22:33:33.263 に答える
1

通常、JCE 暗号は非常に基本的なものです。整合性とキーのテストを含む完全な機能の保護が必要な場合は、それらを組み合わせる必要があります。いつものように、自分でデバイスを作成しない方がよいでしょう。したがって、PKCS7/12 や PGP などのより高レベルの形式を選択することをお勧めします。

使用するパディングによっては、間違ったキーで解読しようとすると、一部の暗号で PaddingException が発生します。整合性チェックを強化するには、HMAC バイトで構成されるパディングを使用します。

JCE にはかなり完全なメソッドが含まれています。それは AESWrap アルゴリズムです。パディングされたデータが必要ですが、整合性が確保されます。RFC 3537 で説明されているように、長さバイトと組み合わせるのが最適です。これは、少量のシークレット (対称キーなど) のみを対象としていることに注意してください。RFC3537 パディングは 255 バイトに制限されています。

これをパスワード派生キーで使用するには、次を使用できます。

char[] pass = ... // your password
byte[] codeBytes = ... // up to 255 bytes you want to protect

// generate wrapping key from password
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
byte[] salt = new byte[16]; rand.nextBytes(salt);
SecretKey kek = f.generateSecret(new PBEKeySpec(pass, salt, 1000, 128));
kek = new SecretKeySpec(password.getEncoded(), "AES"); // convert into AES

// RFC3537 padding (lengthbyte)
byte[] wrappedCodeBytes = new byte[codeBytes + 1 % 8];
System.arraycopy(codeBytes,0,wrappedCodeBytes,1,wrappedCodeBytes.length);
paddedCodeBytes[0]=(byte)codeBytes.length;
byte[] pad = new byte[paddedCodeBytes.length - codeBytes.length -1]; rand.nextBytes(pad);
System.arraycopy(pad,0,paddedCodeBytes,codeBytes.length+1,pad.length);
// AESWrap is WRAP_MODE:needs a SecretKey 
SecretKey paddedCodeKey = new SecretKeySpec(paddedCodeBytes, "RAW");

// now wrap the password with AESWrap kek is 128 bit
Cipher c = Cipher.getInstance("AESWrap"); // default IV
c.init(Cipher.WRAP_MODE, kek);
byte[] result = c.warp(paddedCodeKey);

アンラップは演習として読者に残します :) いずれにせよ、PBKDF2 からはより多くのエントロピーが期待できないため、コード例では 128 ビットのキーサイズを使用します。

これにより、間違ったパスワードが高い確率で検出されることに注意してください。批評家の中には、これを AESWrap の弱点と見なす人もいます。

于 2012-08-31T22:35:46.783 に答える