使用密码短语的带有 CBC 的 Java AES
我想用 Java 实现 256 密钥 AES 和 CBC 加密.收件人将 256 位密码作为字符串absnfjtyrufjdngjvhfgksdfrtifghkv"发送给我,并且使用以下 openssl 命令可以完美运行:
I want to implement 256 key AES with CBC encryption with Java. Recipient sent me 256 bit passphrase as a String 'absnfjtyrufjdngjvhfgksdfrtifghkv' and it perfectly works using this openssl command:
echo test | openssl enc -aes-256-cbc -a -k 'absnfjtyrufjdngjvhfgksdfrtifghkv'
base64格式的输出为:U2FsdGVkX1/yA4J8T+i1M3IZS+TO/V29rBJNl2P88oI=
The output in base64 format is : U2FsdGVkX1/yA4J8T+i1M3IZS+TO/V29rBJNl2P88oI=
当我解密它时,它会返回原始输入字符串:
When i decript it, it returns original input string :
echo U2FsdGVkX1/yA4J8T+i1M3IZS+TO/V29rBJNl2P88oI= | openssl enc -d -aes-256-cbc -a -k 'absnfjtyrufjdngjvhfgksdfrtifghkv'
我的问题是我无法让我的加密在 java 中工作并使用上述命令对其进行解密.我知道我的密钥应该使用我的密码生成.下面是我的代码示例,其中 IV 是随机生成的,密钥是使用密码和随机盐生成的.
My problem is that i cannot make make my encryption work in java and decrypt it with above command. I know that my key should be generated using my passphrase. Below is example of my code where IV is generated randomly and key is generating using passphrase and random salt.
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==,当我尝试运行时:
My java base64 output is XimWIM+8UewzobFOMfevaw== and when I try do run this:
echo XimWIM+8UewzobFOMfevaw= | openssl enc -d -aes-256-cbc -a -k 'absnfjtyrufjdngjvhfgksdfrtifghkv'
我收到错误的幻数"错误.java加密哪一步我做错了?
I get 'bad magic number' error. What step of java encryption I'm doing wrong?
推荐答案
根据this answer,OpenSSL使用了不同的密钥派生算法比您在 Java 代码中使用的算法.因此,用于加密的密钥在您的 OpenSSL 命令和 Java 程序中会有所不同,因此输出会有所不同且不兼容.
According to this answer, OpenSSL uses a different key derivation algorithm than what you are using in your Java code. Therefore, the key used to encrypt will be different in your OpenSSL command and in your Java program, so the output will be different and incompatible.
您还应该查看 OpenSSL 中 密钥派生函数 的文档.显然它在算法中使用 MD5,而您的 Java 代码使用的是 SHA1.它们不会输出相同的密钥.
You should also check the documentation of the key derivation function in OpenSSL. Apparently it uses MD5 in the algorithm, while your Java code is using SHA1. They won't output the same key.
您必须指定完全相同的密钥派生函数,或直接指定密钥,而不是从密码短语派生.
You have to specify exactly the same key derivation function, or specify the key directly, instead of deriving it from a passphrase.
最后,避免为自己创建一个密钥派生函数(您可以使用 bash 和 Java 轻松实现)并坚持标准,如果安全是一个问题(如果不是,为什么还要使用加密?);算法很可能会被破坏.
Finally, avoid creating yourself a key derivation function (that you could easily implement using bash and using Java) and stick to standards, if security is a concern (if it is not, why bother using crypto?); it is most probable that the algorithm will be broken.
相关文章