自動パディングなしで16バイト配列をAESで暗号化および復号化する最も簡単な方法は何ですか?外部ライブラリを使用するソリューションを見つけましたが、可能であればそれを避けたいです。
私の現在のコードは
SecretKeySpec skeySpec = new SecretKeySpec(getCryptoKeyByteArray(length=16)); // 128 bits
Cipher encryptor = Cipher.getInstance("AES");
encryptor.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = encryptor.doFinal(plain);
パディングを防ぐにはどうすればよいですか? plain
データは常に固定長で、独自のパディングが含まれています。 plain
を32バイトにせずに、encrypted
を16バイトにするにはどうすればよいですか?
私のコメントを見てください。申し訳ありませんが、おそらく最初はもっとよく見るべきでした。
"AES"
_を_"AES/CBC/NoPadding"
_に変更しますdecryptor.init(Cipher.DECRYPT_MODE, skeySpec);
をdecryptor.init(Cipher.DECRYPT_MODE, skeySpec, encryptor.gerParameters());
に変更します保存する必要のある初期化ベクトルを必要としないメソッドを使用して、固定長の16バイトのデータのみを暗号化するには、_"AES"
_を_"AES/ECB/NoPadding"
_に変更します。
それがデフォルト なので、私はECBを選びます。
16バイトを超える暗号化が必要な場合は、 ECB以外のものを使用することを検討してください。ECBは、特定の反復検出欠陥 の影響を受けます
このビットマップの例では、この画像には白いブロックが繰り返されているため、ブロックが異なる場所を探すだけで画像の輪郭を推測できます。
1つのブロックのみを暗号化する場合、それは本当に問題ではありません。結合された複数のブロックを暗号化する場合にのみ、ECBが明らかになります。
関連: https://security.stackexchange.com/questions/15740/what-are-the-variables-of-aes
@rossumに同意しますが、それだけではありません:
CTRモードには初期化ベクトル(IV)が必要です。これは「カウンター」です(「CTR」とはこれを指します)。 IVを個別に保存できる場合(保護する必要はありません)、問題なく機能します。データを復号化するときに同じIV値が必要になります。
IVを保存したくない場合、2つの値が同じキーで暗号化されないことを保証できます、固定IV(0の配列でも)を使用することは問題ありません。
同じキー/ IVの組み合わせで複数のメッセージを暗号化するとセキュリティが破壊されるため、上記は非常に重要です。このWikipediaの記事のInitialization vector(IV)セクションを参照してください: http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
コードのAES CTR実装は次のようになります。
SecretKeySpec skeySpec = new SecretKeySpec(getCryptoKeyByteArray(length=16));
Cipher encryptor = Cipher.getInstance("AES/CTR/NoPadding");
// Initialisation vector:
byte[] iv = new byte[encryptor.getBlockSize()];
SecureRandom.getInstance("SHA1PRNG").nextBytes(iv); // If storing separately
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
encryptor.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
byte[] encrypted = encryptor.doFinal(plain);
CTRモードではパディングは必要ありません:"AES/CTR/NoPadding"
。