gpt4 book ai didi

java - 如何允许使用错误 key 完成解密而不抛出 BadPaddingException?

转载 作者:行者123 更新时间:2023-12-01 12:12:48 27 4
gpt4 key购买 nike

我需要 ECB 中的简单 AES 加密系统。我现在有一个工作,从某种意义上说,连续两次给出相同的 key ,它将正确地加密和解密消息。

但是,如果我使用两个不同的 key 进行加密/解密,程序会抛出javax.crypto.BadPaddingException:给定的最终 block 未正确填充。我需要程序提供不正确的解密,大概是一些看起来像加密字符串的东西。这是我的代码:

    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"等的缺点,但这不是我目前关心的问题。)感谢您的所有帮助。

最佳答案

PKCS#5 填充具有非常具体的结构,因此如果您希望使用错误的 key 顺利完成解密,则无法继续使用它。

实现目标的一个好方法可能是使用流操作模式,而不是 block 模式。在流模式下,输入 key 用于生成看似随机数据的永无止境的流,该流与密文进行异或以生成明文(反之亦然)。如果您使用错误的 key ,您将得到与原始明文大小相同的无意义数据。

这是一个基于您的原始代码的简单示例。我使用全零的 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

关于java - 如何允许使用错误 key 完成解密而不抛出 BadPaddingException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27181971/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com