在Java中没有salt或iv的情况下,代码无法解密

时间:2015-06-23 01:39:31

标签: java security encryption aes password-encryption

我有一个密文和一个256位密钥,使用AES解密它。没有盐或静脉注射。我正在使用Java。我已经在线实现了许多解决方案,但它们都使用盐和输入向量。以下构建正常,但在运行时失败:"找不到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");
}

}

3 个答案:

答案 0 :(得分:1)

您可以使用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类剥离填充,结果将是15字节的明文:

807060504030201008070605040302

这应该足以让您使用Java类并重现相同的结果。我只想告诉你,这将适用于AES 256 ECB,不涉及任何IV或盐。

答案 1 :(得分:0)

IV通常与加密模式(如CBC)一起使用。我假设Schneier在这里使用ECB,这并不涉及IV。 ECB模式通常不在现实世界中使用,因为它缺乏安全性。我建议你看一下WIkipedia modes of operation文章。盐更多了。

如果您同意这是您正在处理的问题,那么您可能希望查看here以便在ECB模式下加密Java代码。

答案 2 :(得分:0)

这里的答案都是关于使用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