2017-07-11 412 views
0

在Android上,我沒有任何問題加密消息並獲得iv。Android上的基於密碼的AES加密和CryptoJS的解密

String Test = "Lorem ipsum dolor sit amet, ..."; 
String password = "test"; 

KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
sr.setSeed(password.getBytes("UTF8")); 
kgen.init(256, sr); 
SecretKey skey = kgen.generateKey(); 

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
SecretKeySpec skeySpec = new SecretKeySpec(skey.getEncoded(), "AES"); 
c.init(Cipher.ENCRYPT_MODE, skeySpec); 
byte[] decrypted = c.doFinal(Test.getBytes()); 
decrypted = Base64.encodeBase64(decrypted); 
byte[] iv = Base64.encodeBase64(c.getIV()); 
Log.d("encryptString", new String(decrypted)); 
Log.d("encryptString iv", new String(iv)); 

輸出例如:

encryptString: 2NVoJzMkPphwUJc2h/4LfsmAwyJlejbWKGLG2ACNbaI= 
encryptString iv: YX5SF+cFwzv1I4OiGrJk3A== 

當我動過的JavaScript側I第一base64編碼轉換爲字節。然後通過CryptoJS AES Decrypt函數運行它。

var decrypt = CryptoJS.enc.Base64.parse("2NVoJzMkPphwUJc2h/4LfsmAwyJlejbWKGLG2ACNbaI="); 
var iv = CryptoJS.enc.Base64.parse("YX5SF+cFwzv1I4OiGrJk3A=="); 
var password = "test"; 

var encrypted = CryptoJS.AES.decrypt(decrypt.toString(), password, { 
    iv: iv, 
    mode: CryptoJS.mode.CBC, 
    padding: CryptoJS.pad.Pkcs7 
}); 

輸出總是空的。 Android上還有其他東西,我還需要傳遞給CryptoJS?

+0

如果您僅使用對稱加密,則需要在服務器和客戶端使用完全相同的密鑰。如果您將加密密鑰從服務器發送到客戶端或其他方式需要加密對稱加密密鑰。最簡單的方法是使用TLS。如果你使用TLS,那麼數據和密鑰都是加密的,所以你不需要自己加密。這不提供任何安全性,只是一點混淆。您應該閱讀:https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/ –

+0

切勿使用SHA1PRNG或其他'SecureRandom'實現從密碼派生密鑰。它不會總是有效,因爲PRNG的密碼可能不是隨機性的唯一來源。請使用PBKDF2來從密碼派生密鑰。供參考:https://stackoverflow.com/a/20134336/1816580 –

+0

關鍵是以完全不同的方式派生。 CryptoJS使用EVP_BytesToKey,Android使用* something *隨API版本更改。只需使用兩者都支持的相同程序(即PBKDF2)。 –

回答

3

發現問題,它不是一個填充問題。

正如其他人所說,它與我使用SecureRandom.getInstance(「SHA1PRNG」)的事實有關。

我更正了我的代碼中的問題,在Android和PBKDF2上使用CryptoJS上的PBEKeySpec生成密鑰。然後,只需按照相同的步驟:在Android從運行代碼

String Test = "Lorem ipsum dolor sit amet, ..."; 
String password = "test"; 

byte[] salt = new String("12345678").getBytes("Utf8"); 
int iterationCount = 2048; 
int keyStrength = 256; 

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keyStrength); 
SecretKey tmp = factory.generateSecret(spec); 

Log.d("encryptString Key: ", new String(Base64.encodeBase64(tmp.getEncoded()))); 

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
c.init(Cipher.ENCRYPT_MODE, tmp); 
byte[] decrypted = c.doFinal(Test.getBytes()); 
decrypted = Base64.encodeBase64(decrypted); 
byte[] iv = c.getIV(); 

Log.d("encryptString: ", new String(decrypted)); 
Log.d("encryptString iv:", new String(Base64.encodeBase64(iv))); 

輸出示例:

encryptString Key:: ueTU6u4PXbm86zy+UtlQfeh55xZorA58W3fKKBypheM= 
encryptString:: ii8UNoi4xG1zGC8RyzHKu6JMkxixkK7LTPxGMaCHGNk= 
encryptString iv:: nwy2VHctPnXOd/rahPFiWg== 

現在我們產生一個JavaScript同樣PBKDF2鍵,輸入輸出上面到下面示例代碼:

var salt = CryptoJS.enc.Utf8.parse("12345678"); 
 
var password = "test"; 
 
var keyBits = CryptoJS.PBKDF2(password, salt, { 
 
    hasher: CryptoJS.algo.SHA1, 
 
    keySize: 8, 
 
    iterations: 2048 
 
}); 
 

 
var iv = CryptoJS.enc.Base64.parse("nwy2VHctPnXOd/rahPFiWg=="); 
 
var message = CryptoJS.enc.Base64.parse("ii8UNoi4xG1zGC8RyzHKu6JMkxixkK7LTPxGMaCHGNk="); 
 

 
var encrypted = CryptoJS.AES.decrypt("ii8UNoi4xG1zGC8RyzHKu6JMkxixkK7LTPxGMaCHGNk=", keyBits, { 
 
    iv: iv, 
 
    padding: CryptoJS.pad.Pkcs7, 
 
    mode: CryptoJS.mode.CBC 
 
}); 
 

 
console.log(encrypted.toString(CryptoJS.enc.Utf8));
<!doctype html> 
 

 
<html> 
 

 
<head> 
 
</head> 
 

 
<body> 
 
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script> 
 
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/pbkdf2.min.js"></script> 
 
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/aes.min.js"></script> 
 
</body> 
 

 
</html>

JavaScript輸出:

"Lorem ipsum dolor sit amet, ..." 
+0

@ Tangela wiz,我得到錯誤在散列:CryptoJS.algo.SHA1, – KCN

+0

你可以發佈相同的android解密和javascript加密 – KCN

+0

更新: Base64.encodeBase64(iv)更改爲Base64.encode(iv,Base64。 DEFAULT) Base64.encodeBase64(解密);更改爲Base64.encode(解密,Base64.DEFAULT); – comeback4you