2013-02-04 90 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的具體細節。 –

相關問題