Java的AES与CBC使用密码(Java AES with CBC using passphras

2019-08-16 17:55发布

我想实现与CBC加密与Java 256个键AES。 收件人给我发了256位密码作为一个字符串“absnfjtyrufjdngjvhfgksdfrtifghkv”和它完美的作品使用此命令的OpenSSL:

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

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

当我decript,它返回原来的输入字符串:

 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加密我做错了吗?

Answer 1:

根据这个答案 ,OpenSSL的使用比您正在使用在Java代码中有什么不同的密钥派生算法。 因此,使用加密密钥将在您的OpenSSL命令,并在Java程序不同,所以输出会有所不同,不兼容。

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

你必须指定完全相同的密钥导出函数,或直接指定密钥,而不是从口令派生它。

最后,避免创建自己的密钥推导函数(你可以很容易地实现使用bash和使用Java),坚持标准,如果担心安全问题(如果不是,为什么还要使用密码?); 它是最可能的,该算法将被打破。



文章来源: Java AES with CBC using passphrase