问题
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'
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'
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)));
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'
I get 'bad magic number' error. What step of java encryption I'm doing wrong?
回答1:
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.
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.
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.
来源:https://stackoverflow.com/questions/14695766/java-aes-with-cbc-using-passphrase