0

ECB で単純な AES 暗号化システムが必要です。同じキーを 2 回続けて指定すると、メッセージを正しく暗号化および復号化するという意味で、現時点では 1 つが機能しています。

ただし、暗号化/復号化に 2 つの異なるキーを使用すると、プログラムはjavax.crypto.BadPaddingException: Given final block not properly padded. おそらく暗号化された文字列のように見える、誤った復号化を提供するプログラムが必要です。これが私のコードです:

    public static byte[] encrypt(byte[] plaintext, String key) throws Exception {
        char[] password = key.toCharArray();
        byte[] salt = "12345678".getBytes();
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);
        byte[] ciphertext = cipher.doFinal(plaintext);  
        return ciphertext;
    }

    public static byte[] decrypt(byte[] ciphertext, String key) throws Exception {
        char[] password = key.toCharArray();
        byte[] salt = "12345678".getBytes();
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
        SecretKey tmp = factory.generateSecret(spec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secret);
        byte[] plaintext = cipher.doFinal(ciphertext);  
        return plaintext;
    }

(注:ECB、salt = "12345678"などを使用することの欠点は認識していますが、現時点では問題ではありません。)すべての助けに感謝します。

4

1 に答える 1

1

PKCS#5 パディングは非常に特殊な構造を持っているため、間違ったキーで復号化をエラーなしで完了させたい場合は、引き続き使用することはできません。

目標を達成するための良い方法は、ブロック モードではなく、ストリーム モードの操作を使用することです。ストリーム モードでは、入力キーを使用して一見ランダムなデータの終わりのないストリームを生成し、これを暗号文と XOR して平文を生成します (逆も同様です)。間違った鍵を使用すると、元の平文と同じサイズの無意味なデータが出力されます。

元のコードに基づいた簡単な例を次に示します。私はすべてゼロの IV を使用していますが、そのうちランダムな値になるように改善することをお勧めします (注: この値を暗号文と共に保存する必要があります)。

public static void main(String[] args) throws Exception {  
  byte[] plaintext = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  byte[] ciphertext = encrypt(plaintext, "foo");

  byte[] goodDecryption = decrypt(ciphertext, "foo");
  byte[] badDecryption = decrypt(ciphertext, "bar");  

  System.out.println(DatatypeConverter.printHexBinary(goodDecryption));
  System.out.println(DatatypeConverter.printHexBinary(badDecryption));
}

public static SecretKey makeKey(String key) throws GeneralSecurityException {
  char[] password = key.toCharArray();
  byte[] salt = "12345678".getBytes();
  SecretKeyFactory factory =
      SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
  KeySpec spec = new PBEKeySpec(password, salt, 65536, 128);
  SecretKey tmp = factory.generateSecret(spec);
  return new SecretKeySpec(tmp.getEncoded(), "AES");
}

public static byte[] encrypt(byte[] plaintext, String key) throws Exception {
  SecretKey secret = makeKey(key);
  Cipher cipher = Cipher.getInstance("AES/OFB8/NoPadding");
  cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(new byte[16]));
  return cipher.doFinal(plaintext);
}

public static byte[] decrypt(byte[] ciphertext, String key) throws Exception {
  SecretKey secret = makeKey(key);
  Cipher cipher = Cipher.getInstance("AES/OFB8/NoPadding");
  cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(new byte[16]));
  return cipher.doFinal(ciphertext);
}

出力:

00010203040506070809
5F524D4A8D977593D34C
于 2014-11-28T09:07:22.477 に答える