【问题标题】:Java Decryption of openssl aes-256-ctr encrypted filejava解密openssl aes-256-ctr加密文件
【发布时间】:2020-01-20 13:59:30
【问题描述】:

我尝试在 java 中解密一个通过 openssl 加密的文件:

openssl enc -aes-256-ctr -in raw.zip -out encrypted.zip.enc -pass stdin

我的实现目前看起来很糟糕,因为它只是一个划痕。

 public static void main(String[] args)
    throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {

    FileInputStream fis = new FileInputStream(new File("/tmp/encrypted.zip.enc"));
    /* Derive the key, given password and salt. */
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    byte[] salt = new byte[8];
    fis.read(salt, 0, 8);// Salted__
    fis.read(salt, 0, 8);// real Salt

    KeySpec spec = new PBEKeySpec("myPassphrase".toCharArray(), salt, 65536, 256);
    SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); 

    // build the initialization vector.  This example is all zeros, but it
    // could be any value or generated using a random number generator.
    byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    IvParameterSpec ivspec = new IvParameterSpec(iv);
    Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING");
    cipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
    CipherInputStream inputStream = new CipherInputStream(fis, cipher);
    FileOutputStream fos = new FileOutputStream(new File("/tmp/decrypted.zip"));

    byte[] buffer = new byte[1024];
    int len;
    while ((len = inputStream.read(buffer)) != -1) {
        fos.write(buffer, 0, len);
    }
}

文件和以前不一样了。哈希值不同。我猜,密钥有问题。这样对吗?我应该使用其他实例吗?

【问题讨论】:

标签: java algorithm encryption cryptography aes


【解决方案1】:

如果你使用openssl enc 而不使用-pbkdf2,它会使用一些内部密钥派生函数。我的例子:

openssl 命令:

openssl enc -aes-256-ctr -in 1.txt -out 1.enc -pbkdf2 -iter 1000 -pass pass:qwerty -p

参数-p 输出生成的密钥。在我的情况下是:

salt=063C06BA16675384
key=45743B02A171425197014D80A08D1024CD97587272BAEBE1F1F0FC3AC0164AB2
iv =9DF736227817CBEC9DF5397F1C05F31A

Java 代码:

public static void main(String[] args) throws Exception {

    FileInputStream fis = new FileInputStream(new File("1.enc"));

    fis.skip(8);
    byte[] salt = new byte[8];
    fis.read(salt);

    System.out.println("salt=" + byteArrayToHex(salt));

    // you used PBKDF2 with SHA1, but openssl uses SHA256
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    // you should generate 48 bytes, key and IV
    KeySpec spec = new PBEKeySpec("qwerty".toCharArray(), salt, 1000, 48 * 8);
    byte[] bytes = factory.generateSecret(spec).getEncoded();

    byte[] key = Arrays.copyOfRange(bytes, 0, 32);
    byte[] nonce = Arrays.copyOfRange(bytes, 32, 48);

    System.out.println("key=" + byteArrayToHex(key));
    System.out.println("nonce=" + byteArrayToHex(nonce));

    IvParameterSpec iv = new IvParameterSpec(nonce);
    SecretKey secret = new SecretKeySpec(key, "AES"); 
    Cipher cipher = Cipher.getInstance("AES/CTR/PKCS5PADDING");
    cipher.init(Cipher.DECRYPT_MODE, secret, iv);
    CipherInputStream cis = new CipherInputStream(fis, cipher);
    System.out.println(new String(cis.readAllBytes()));
}

public static String byteArrayToHex(byte[] a) {
    StringBuilder sb = new StringBuilder(a.length * 2);
    for (byte b: a)
       sb.append(String.format("%02x", b));
    return sb.toString();
}

它输出 key 和 IV,因此您可以与 openssl 输出进行比较。我用的是openssl 1.1.1

【讨论】:

  • 我的 Mac 上使用的是 2.6.5,没有选项:-pbkdf2
  • 没有2.6.5版本的openssl,这个一定是libressl
  • 天哪,对不起,没错。抱歉耽搁了,我正在与合作伙伴联系,他没有回答我更改加密文件命令的要求。在 Mac 上,我目前只能使用 LibreSSL 进行加密。有更多信息后,我会回复你。我现在在 docker 容器中对其进行测试,以调查正确的行为。
猜你喜欢
  • 2014-08-05
  • 2017-08-08
  • 2011-03-09
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多