java - java解密openssl aes-256-ctr加密文件
问题描述
我尝试在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);
}
}
该文件与以前不同。哈希值不同。我猜,密钥有问题。这样对吗?我应该使用其他实例吗?
解决方案
如果不使用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
推荐阅读
- javascript - 如何更改此 iframe 的大小?
- java - 方法 publishProgress 必须从工作线程调用,目前推断线程为主线程
- windows - 无法从沙箱中重命名文件
- gcloud - 我们可以使用 gmail 帐户一次性登录多个 gcloud 项目吗?
- android - Kotlin 多平台:集成引用托管 git 存储库的 cocoapods?
- node.js - 编写一个打印“Hello World!”的nodejs程序 作为应用程序所有路由的输出
- javascript - 向数组添加常用对象和格式
- node.js - ExpressJS 中的 API 错误处理和数据验证
- c# - 使用 travis 和 sonarcloud 分析 c# 项目给出“没有代码行”
- php - 如何获取从laravel中的url收集的数据?