使用不同的 Cipher 对象解密时出现 BadPaddingException
BadPaddingException when decrypting using a different Cipher object
请原谅我的黑客工作!在编码方面仍然是新手,并且正在利用大量系统输出来解决问题,这是我在 Whosebug 的第一个 post。感谢您的帮助!
所以我一直在尝试使用 javax.crypto.Cipher API 加密 String 对象,我发现了一些成功,但只有当它使用 Cipher 对象的相同实例时.但是,出于我的项目的目的,我将文本 (String) 加密到文本文件并从文本文件中解密文本,并且不会每次都访问相同的 Cipher 对象。
我认为问题不在于字节数组和字符串之间的转换,因为 Base64 编码器似乎已经解决了这个问题。字节数组的输出是相同的预编码和 post 解码,因此应该在解密阶段将其作为一个问题隔离开来。怎样做才能使我的 decryptPW 方法可以使用不同的 Cipher 实例(传递相同的参数)而不触发 BadPaddingException?
private static String encryptPW(String pw){
byte[] pwBytes = pw.getBytes();
byte[] keyBytes = "0123456789abcdef".getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
try {
Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encryptedBytes = ciph.doFinal(pwBytes);
pw = Base64.getEncoder().encodeToString(ciph.doFinal(pwBytes));
for (byte b : encryptedBytes){
System.out.print(b);
}
System.out.println();
} catch (Exception e){
e.printStackTrace();
}
return pw;
}
private static String decryptPW(String pw){
byte[] pwBytes = Base64.getDecoder().decode(pw.getBytes());
for (byte b : pwBytes){
System.out.print(b);
}
System.out.println();
byte[] keyBytes = "0123456789abcdef".getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
try {
Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.DECRYPT_MODE, keySpec, ciph.getParameters());
pw = new String(ciph.doFinal(pwBytes));
} catch (Exception e){
e.printStackTrace();
}
return pw;
}
再次感谢!
当您使用CBC mode时,您需要保存来自加密密码的随机初始化向量 (IV),并将其提供给解密密码。
您可以在初始化后从加密密码中获取它,例如:
ciph.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] iv = ciph.getIV();
并将其提供给解密密码,例如:
ciph.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
你需要想出一个保存IV的方法。一种常见的方法是在加密数据前加上 IV,这样当您需要初始化解密密码时就可以使用它。不需要保密。
请原谅我的黑客工作!在编码方面仍然是新手,并且正在利用大量系统输出来解决问题,这是我在 Whosebug 的第一个 post。感谢您的帮助!
所以我一直在尝试使用 javax.crypto.Cipher API 加密 String 对象,我发现了一些成功,但只有当它使用 Cipher 对象的相同实例时.但是,出于我的项目的目的,我将文本 (String) 加密到文本文件并从文本文件中解密文本,并且不会每次都访问相同的 Cipher 对象。
我认为问题不在于字节数组和字符串之间的转换,因为 Base64 编码器似乎已经解决了这个问题。字节数组的输出是相同的预编码和 post 解码,因此应该在解密阶段将其作为一个问题隔离开来。怎样做才能使我的 decryptPW 方法可以使用不同的 Cipher 实例(传递相同的参数)而不触发 BadPaddingException?
private static String encryptPW(String pw){
byte[] pwBytes = pw.getBytes();
byte[] keyBytes = "0123456789abcdef".getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
try {
Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encryptedBytes = ciph.doFinal(pwBytes);
pw = Base64.getEncoder().encodeToString(ciph.doFinal(pwBytes));
for (byte b : encryptedBytes){
System.out.print(b);
}
System.out.println();
} catch (Exception e){
e.printStackTrace();
}
return pw;
}
private static String decryptPW(String pw){
byte[] pwBytes = Base64.getDecoder().decode(pw.getBytes());
for (byte b : pwBytes){
System.out.print(b);
}
System.out.println();
byte[] keyBytes = "0123456789abcdef".getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
try {
Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.DECRYPT_MODE, keySpec, ciph.getParameters());
pw = new String(ciph.doFinal(pwBytes));
} catch (Exception e){
e.printStackTrace();
}
return pw;
}
再次感谢!
当您使用CBC mode时,您需要保存来自加密密码的随机初始化向量 (IV),并将其提供给解密密码。
您可以在初始化后从加密密码中获取它,例如:
ciph.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] iv = ciph.getIV();
并将其提供给解密密码,例如:
ciph.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
你需要想出一个保存IV的方法。一种常见的方法是在加密数据前加上 IV,这样当您需要初始化解密密码时就可以使用它。不需要保密。