2013-02-04 52 views
3

我想使用Java的CBC加密实现256密钥AES。收件人发送我的256位密码作为一个字符串 'absnfjtyrufjdngjvhfgksdfrtifghkv',它完美地适用于使用本openssl指令:使用密码CBC的Java AES

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

回答

4

根据this answer,OpenSSL使用与您在Java代码中使用的不同的密钥派生算法。因此,用于加密的密钥在您的OpenSSL命令和Java程序中会有所不同,因此输出将会不同并且不兼容。

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

您必须指定完全相同的密钥派生函数,或者直接指定密钥,而不是从密码中派生密钥。最后,如果安全是一个问题(如果不是,为什么还要使用加密?),避免创建自己的密钥派生函数(您可以使用bash和使用Java轻松实现)并坚持标准。该算法很可能会被破坏。

+0

Tnx为您的答案。我想知道是否有任何函数返回传递给此函数的所有可能的算法: SecretKeyFactory.getInstance(“algorithm”) 因为我很难找到正确的字符串作为openssl算法(它不是只是“MD5”) 在阅读openssl如何生成密钥后,它看起来也必须从密码生成IV,这是真的吗?或者我可以使用随机生成的IV获得正确的结果,如我的示例中所示? –

+0

Java中是否还有其他库可以完成与openssl相同的工作,并且只需要使用密码并加密数据,而无需手动生成所有这些步骤?我认为其他编程语言(如Ruby ..)具有这种特性,所以它必须是Java中类似的东西。 –

+0

你究竟想要达到什么目的?没有更多的信息,给出好的建议有点困难。什么/谁会加密数据?它将如何传输?什么/谁会解密密文?针对你想保护什么(简单的窃听/攻击者篡改密文传输等)?无论如何,你是否考虑过在您的Java程序中使用OpenSSL作为外部过程的可能性?这样,您就不需要打扰OpenSSL和Java KDF的具体细节。 –

相关问题