Java 中没有盐或 iv 的代码无法解密
Code fails for decrypting without salt or iv in Java
我有一个密文和一个使用 AES 解密的 256 位密钥。没有盐或静脉注射。我正在使用 Java。我在网上实现了很多解决方案,但它们都使用盐和输入向量。以下构建正常,但在运行时失败:"Salt not found." What salt?
public class AESFileDecryption {
public static void main(String[] args) throws Exception {
String password = "80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01";
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray());
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
// file decryption
Cipher cipher = Cipher.getInstance();
cipher.init(Cipher.DECRYPT_MODE,secret);
FileInputStream fis = new FileInputStream("encryptedfile.des");
FileOutputStream fos = new FileOutputStream("plainfile_decrypted.txt");
byte[] in = new byte[64];
int read;
while ((read = fis.read(in)) != -1) {
byte[] output = cipher.update(in, 0, read);
if (output != null)
fos.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
System.out.println("File Decrypted");
}
}
IV 通常与 CBC 等加密模式一起使用。我假设 Schneier 在这里使用的是 ECB,它不涉及 IV。 ECB 模式在现实世界中通常不使用,因为它缺乏安全性。我建议您查看 WIkipedia modes of operation 文章。盐就更便宜了。
如果您同意这是您正在处理的问题,那么您可能需要查看 here 以获取 java 代码以在 ECB 模式下加密。
您可以使用AES 的简单ECB 模式解密练习3.8 中的密文,该模式不使用IV。因为你有密钥,所以不需要盐(没有密钥推导)。在 Java 中使用 AES 256 ECB 模式,并如图所示传递密钥。命令行中的这些 openssl 命令表明这将起作用:
你要将书中所示的十六进制转换成字节串,例如:
echo '539B333B39706D149028CFE1D9D4A407' | xxd -r -p
你必须使用32字节的字符串作为密钥,例如,openssl命令行使用-K参数为你将十六进制转换为字节:
-K 80000000000000000000000000000000000000000000000000000000000001
并且您可以将生成的二进制明文转换回十六进制字符串以供查看,如
xxd -p
例如:
echo '539B333B39706D149028CFE1D9D4A407' | xxd -r -p | openssl enc -aes-256-ecb -nopad -d -K 8000000000000000000000000000000000000000000000000000000000000001 | xxd -p
结果是:
80706050403020100807060504030201
如果让 Java class 去除填充,结果将是 15 个字节的明文:
807060504030201008070605040302
这应该足以让您使用 Java classes 并重现相同的结果。我只是想向您展示这将适用于 AES 256 ECB,不涉及任何 IV 或盐。
这里关于使用 ECB 的两个答案都是正确的,因此不需要 IV(或填充)。这是问题 3.8 的更新 Java 答案:
String hexCipherText = "539b333b39706d149028cfe1d9d4a407";
String hexSecretKey = "80000000000000000000000000000000" +
"00000000000000000000000000000001";
byte[] secretKey = DatatypeConverter.parseHexBinary (hexSecretKey);
byte[] cipherText = DatatypeConverter.parseHexBinary (hexCipherText);
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey,"AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] plainText = cipher.doFinal(cipherText);
String hexPlainText = DatatypeConverter.printHexBinary(plainText);
如果您遇到错误 java.security.InvalidKeyException: Illegal key size or default parameters
并且您使用的是 Oracle JDK,那么您可能还需要下载 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.
我有一个密文和一个使用 AES 解密的 256 位密钥。没有盐或静脉注射。我正在使用 Java。我在网上实现了很多解决方案,但它们都使用盐和输入向量。以下构建正常,但在运行时失败:"Salt not found." What salt?
public class AESFileDecryption {
public static void main(String[] args) throws Exception {
String password = "80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01";
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password.toCharArray());
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
// file decryption
Cipher cipher = Cipher.getInstance();
cipher.init(Cipher.DECRYPT_MODE,secret);
FileInputStream fis = new FileInputStream("encryptedfile.des");
FileOutputStream fos = new FileOutputStream("plainfile_decrypted.txt");
byte[] in = new byte[64];
int read;
while ((read = fis.read(in)) != -1) {
byte[] output = cipher.update(in, 0, read);
if (output != null)
fos.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
System.out.println("File Decrypted");
}
}
IV 通常与 CBC 等加密模式一起使用。我假设 Schneier 在这里使用的是 ECB,它不涉及 IV。 ECB 模式在现实世界中通常不使用,因为它缺乏安全性。我建议您查看 WIkipedia modes of operation 文章。盐就更便宜了。
如果您同意这是您正在处理的问题,那么您可能需要查看 here 以获取 java 代码以在 ECB 模式下加密。
您可以使用AES 的简单ECB 模式解密练习3.8 中的密文,该模式不使用IV。因为你有密钥,所以不需要盐(没有密钥推导)。在 Java 中使用 AES 256 ECB 模式,并如图所示传递密钥。命令行中的这些 openssl 命令表明这将起作用:
你要将书中所示的十六进制转换成字节串,例如:
echo '539B333B39706D149028CFE1D9D4A407' | xxd -r -p
你必须使用32字节的字符串作为密钥,例如,openssl命令行使用-K参数为你将十六进制转换为字节:
-K 80000000000000000000000000000000000000000000000000000000000001
并且您可以将生成的二进制明文转换回十六进制字符串以供查看,如
xxd -p
例如:
echo '539B333B39706D149028CFE1D9D4A407' | xxd -r -p | openssl enc -aes-256-ecb -nopad -d -K 8000000000000000000000000000000000000000000000000000000000000001 | xxd -p
结果是:
80706050403020100807060504030201
如果让 Java class 去除填充,结果将是 15 个字节的明文:
807060504030201008070605040302
这应该足以让您使用 Java classes 并重现相同的结果。我只是想向您展示这将适用于 AES 256 ECB,不涉及任何 IV 或盐。
这里关于使用 ECB 的两个答案都是正确的,因此不需要 IV(或填充)。这是问题 3.8 的更新 Java 答案:
String hexCipherText = "539b333b39706d149028cfe1d9d4a407";
String hexSecretKey = "80000000000000000000000000000000" +
"00000000000000000000000000000001";
byte[] secretKey = DatatypeConverter.parseHexBinary (hexSecretKey);
byte[] cipherText = DatatypeConverter.parseHexBinary (hexCipherText);
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey,"AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] plainText = cipher.doFinal(cipherText);
String hexPlainText = DatatypeConverter.printHexBinary(plainText);
如果您遇到错误 java.security.InvalidKeyException: Illegal key size or default parameters
并且您使用的是 Oracle JDK,那么您可能还需要下载 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.