使用密码短语的 Java AES 和 CBC

2023-12-02

我想用 Java 实现 256 密钥 AES 和 CBC 加密。收件人以字符串“absnfjtyrufjdngjvhfgksdfrtifghkv”的形式向我发送了 256 位密码,使用以下 openssl 命令可以完美运行:

 echo test | openssl enc  -aes-256-cbc -a -k 'absnfjtyrufjdngjvhfgksdfrtifghkv'

Base64 格式的输出为: U2FsdGVkX1/yA4J8T+i1M3IZS+TO/V29rBJNl2P88oI=

当我解密它时,它返回原始输入字符串:

 echo U2FsdGVkX1/yA4J8T+i1M3IZS+TO/V29rBJNl2P88oI= | openssl enc -d -aes-256-cbc -a -k 'absnfjtyrufjdngjvhfgksdfrtifghkv'     

我的问题是我无法使我的加密在java中工作并用上面的命令解密它。我知道我的密钥应该使用我的密码生成。下面是我的代码示例,其中 IV 是随机生成的,密钥是使用密码和随机盐生成的。

byte[] input = "test".getBytes();
String passphrase = "absnfjtyrufjdngjvhfgksdfrtifghkv";
int saltLength = 8; 

SecureRandom random = new SecureRandom();

//randomly generate salt
byte[] salt = new byte[saltLength];
random.nextBytes(salt);

// generating key from passphrase and salt
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, 1024, 256);
SecretKey key = factory.generateSecret(spec);
SecretKey kspec = new SecretKeySpec(key.getEncoded(), "AES");

// randomly generate IV
byte iv[] = new byte[16];
random.nextBytes(iv);
IvParameterSpec ips = new IvParameterSpec(iv);

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, kspec, ips);
byte[] encryptedData = c.doFinal(input);
System.out.println(new String(Base64.encodeBase64(encryptedData)));

我的 java base64 输出是 XimWIM+8UewzobFOMfevaw== ,当我尝试运行此命令时:

echo XimWIM+8UewzobFOMfevaw= | openssl enc -d -aes-256-cbc -a -k   'absnfjtyrufjdngjvhfgksdfrtifghkv'

我收到“错误的幻数”错误。 java加密的哪一步我做错了?


根据这个答案,OpenSSL 使用与您在 Java 代码中使用的密钥派生算法不同的密钥派生算法。因此,OpenSSL 命令和 Java 程序中用于加密的密钥将不同,因此输出将不同且不兼容。

您还应该检查以下文档密钥导出函数在 OpenSSL 中。显然它在算法中使用MD5,而你的Java代码使用SHA1。他们不会输出相同的密钥。

您必须指定完全相同的密钥派生函数,或者直接指定密钥,而不是从密码短语派生它。

最后,避免自己创建一个密钥派生函数(您可以使用 bash 和 Java 轻松实现)并坚持标准,如果安全性是一个问题(如果不是,为什么还要使用加密呢?);该算法很可能会被破坏。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用密码短语的 Java AES 和 CBC 的相关文章

随机推荐