【问题标题】:Decrypt AES encrypted file in java在java中解密AES加密文件
【发布时间】:2012-02-18 12:51:43
【问题描述】:

我有一个使用 AES 使用 java 应用程序加密的文件。我也有一个密钥文件被加密了。但我不明白如何使用密钥解密文件。大多数教程和示例会在一处创建临时随机密钥、加密文件和解密文件。 那么,问题是如何指定必须用于解密的密钥?

编辑: 我发现的示例使用以下代码生成密钥。我不知道我可以在哪里使用我的密钥。

KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey key = kgen.generateKey();

【问题讨论】:

  • 你不能把你的密钥放到教程中来代替随机密钥吗?还是您实际上需要将密码和盐转换为密钥位?如果您将我们指向您正在查看的同一教程(和/或在此处引用一些代码),我们可能会帮助您弄清楚如何更改它。
  • @Rup 我认为这只是一个小转换问题,需要将字节转换为Java Key实例。

标签: java key aes encryption


【解决方案1】:

如果对您有帮助,请尝试以下方法。

private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data)
        throws Exception
{
    int minSize = cipher.getOutputSize(data.length);
    byte[] outBuf = new byte[minSize];
    int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
    int length2 = cipher.doFinal(outBuf, length1);
    int actualLength = length1 + length2;
    byte[] result = new byte[actualLength];
    System.arraycopy(outBuf, 0, result, 0, result.length);
    return result;
}

private static byte[] decrypt(byte[] cipher, byte[] key, byte[] iv) throws Exception
{
    PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(
            new AESEngine()));
    CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
    aes.init(false, ivAndKey);
    return cipherData(aes, cipher);
}

private static byte[] encrypt(byte[] plain, byte[] key, byte[] iv) throws Exception
{
    PaddedBufferedBlockCipher aes = new PaddedBufferedBlockCipher(new CBCBlockCipher(
            new AESEngine()));
    CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key), iv);
    aes.init(true, ivAndKey);
    return cipherData(aes, plain);
}

【讨论】:

  • 我有“org.bouncycastle.crypto.InvalidCipherTextException: pad block损坏”。
  • 检查是否为解密指定了与加密相同的填充。如果您不知道,则指定“无填充”进行解密,并查看最后一个块的末尾以确定用于加密的填充。
  • @rossum: 如果我只知道他们用于加密的填充。
  • @Aleksandr Kravets:使用明确设置的“无填充”解密并检查最后一个块的结尾。这将显示在加密之前添加了哪些填充(如果有)。设置“无填充”将接受最后一个块中的任何内容为有效。
  • @rossum:解密后没有填充。最后一个块包含 7 个字节的值 0x07。任何进一步的方向=)?
【解决方案2】:

答案可以简单地将密钥数据作为字节放入 SecretKeySpec 中,如下所示:

SecretKeySpec aesKey = new SecretKeySpec(myKeyData, "AES");

注意SecretKeySpec实现了Key接口,所以你可以直接在Cipher.init()方法中使用它。所以不需要 SecretKeyFactory,否则你会使用它。

【讨论】:

  • 谢谢,这很有帮助。我解密了文件,但它的内容是二进制混乱。很明显我做错了什么。
  • 整个消息是一团糟,还是只有前 16 个字节?你能给我们更多关于所使用算法的信息吗?如果你指定了一个 IV 向量(如果模式 = CBC)?什么样的填充物?这些您在Cipher.getInstance(<algorithm[opt: /mode][opt: /padding]>); 中指定
  • 整个文件一团糟。故事是这样的:我要解密的文件是来自 HSQLDB 数据库的 .script 文件。通常它是一个包含更改日志的纯文本文件。但是有些人决定使用link 中描述的数据库加密。不知何故,数据库损坏了,客户想要恢复数据。所以我不知道 hsqldb 用于加密的任何加密选项。提供给数据库引擎的参数是“AES”和 128 位密钥。没有别的。
  • 它说数据库支持任何算法,所以很可能它只使用Cipher.getInstance("AES");,这与Cipher.getInstance("AES/ECB/PKCS5Padding");相同(使用Sun Java时)。然而,很可能只有特定部分被加密,您必须确保只解密这些部分。
  • 到目前为止没有运气。上面指定的选项。还是无法解密。
【解决方案3】:

只是为了总结我对路西法的回答。

  1. 如果您不知道使用什么填充进行加密,请使用“无填充”设置进行解密。这将解密所有内容,包括填充,并且不会因为填充不匹配而引发错误。

  2. 解密密文后,请查看输出的最后一个块并查看使用了哪些填充。不同的填充会留下不同的字节模式,因此通常很容易分辨。

  3. 将您的解密方法设置为期望正确的填充类型,它将自动为您删除。

【讨论】:

  • 谢谢大家。原来解密结果是GZIP-ed。现在我有了预期的结果。再次感谢!
  • 对于 unix 专家来说,对你无法弄清楚的输出运行“文件”命令永远不会有什么坏处......
【解决方案4】:

加密/解密一个大型视频而不抛出 JavaOutOfMemoryException 并使用 Java SecureRandom 生成初始化向量的完整示例。还描述了将密钥字节存储到数据库,然后从这些字节重建相同的密钥。

https://stackoverflow.com/a/18892960/185022

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-20
    • 2013-04-19
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    相关资源
    最近更新 更多