2014-10-03 51 views
0

由於幾天我試圖找出爲什麼我在JavaScript(cryptojs)和java不同的加密輸出。我在死衚衕,不知道該怎麼改變,我想我會在這方面失去我的頭。這是完整的代碼,應該很容易複製粘貼以進行測試。你是我最後的希望。 ^^AES加密java和javascript不同的輸出

plainText = plaintext 
password = password 
salt = 3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55 
iv = 3C46C00F42A6044A" 

的Javascript結果= zbohHpV5RtmHiH3cKDY15w ==

Java結果= wVdRQiIqkyVlttkWpCMSpQ ==

的JavaScript的HTML:更新和改變迭代10

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
     <title>Aes Test</title> 
     <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/pbkdf2.js"></script> 
     <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script> 
    </head> 
    <body> 
     <div id="result"></div> 
    </body> 
    <script> 


var password = "password"; 
var salt = "3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55"; 

var plainText = "plaintext"; 
var iv = "3C46C00F42A6044A"; 

var key = CryptoJS.PBKDF2(password, CryptoJS.enc.Hex.parse(salt), {keySize: 128/32, iterations: 10}); 

var a = CryptoJS.AES.encrypt(plainText, key, {iv: CryptoJS.enc.Hex.parse(iv)}).ciphertext.toString(CryptoJS.enc.Base64); 


var result = "encypted: " + a + "<br \>"; 
document.getElementById("result").innerHTML = result; 
    </script> 
</html> 

的Java Main.class

public class main { 

    public static void main(String[] args) throws Exception { 
     String result = Aes.encrypt("plaintext", "password", "3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55", "3C46C00F42A6044A"); 
     System.out.println(result);  
    } 
} 

的Java Aes.class

import java.io.UnsupportedEncodingException; 
import java.security.InvalidAlgorithmParameterException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.KeySpec; 
import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 
import org.apache.commons.codec.binary.Base64; 

public class Aes { 
    private static final int pswdIterations = 10; 
    private static final int keySize = 128; 

    public static String encrypt(String plainText, String password, String salt, String initializationVector) throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { 
     byte[] saltBytes = salt.getBytes("UTF-8"); 
     byte[] ivBytes = initializationVector.getBytes("UTF-8"); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
     KeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, pswdIterations, keySize); 
     SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes)); 
     byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes()); 
     return new Base64().encodeAsString(encryptedTextBytes); 
    } 
} 
+0

不同的填充? – m0skit0 2014-10-03 21:23:25

+0

這是甚至在java中執行的? AES/CBC/PKCS5Padding僅支持128個密鑰長度。 http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html你應該得到非法的密鑰大小例外 – anu 2014-10-03 21:25:46

+0

@Anupam:這些是支持大小的必需*。另外,如果您安裝無限加密管轄權文件,則可以使用更大的密鑰大小。 – 2014-10-03 21:36:27

回答

0

的所有JavaScript代碼首先是錯誤的。試試下面的代碼,看看你的keySize和iterationCount變量是未定義的。

Aes.generateKey = function(salt, passPhrase) { 
    console.log(this.keySize); 
    console.log(this.iterationCount); 
    var key = CryptoJS.PBKDF2(
      passPhrase, 
      CryptoJS.enc.Hex.parse(salt), 
      { keySize: this.keySize, iterations: this.iterationCount }); 
    return key; 
} 

從JavaScript的結果應該是Bttn5HNBIFDQ5hb1IbOFXQ ==

var password = "password"; 
var salt = "3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55"; 

var plainText = "plaintext"; 
var iv = "3C46C00F42A6044A"; 

var key = CryptoJS.PBKDF2(password, CryptoJS.enc.Hex.parse(salt), {keySize: 128/32, iterations: 10000}); 

var a = CryptoJS.AES.encrypt(plainText, key, {iv: CryptoJS.enc.Hex.parse(iv)}).ciphertext.toString(CryptoJS.enc.Base64); 

console.log(a); 
+0

感謝您清除那個。但仍然JavaScript輸出不匹配到java的輸出。Cryptojs將鹽和iv轉換爲十六進制,並在java im轉換爲字節。我能夠將鹽轉換爲十六進制,但不是沒有錯誤的四。也許錯誤在這裏? – wook 2014-10-03 22:24:29

+0

如何轉換字符串(有十六進制值)在Java中的字節數組?你是否使用類似於這篇文章的東西:[鏈接](http://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex -dump-to-a-byte-array-using-java) – pasimako 2014-10-03 23:15:02

+0

是的,類似的東西。還嘗試了鏈接中的方法,只是再次獲得一個新的不同的加密密文。但不匹配javascript <-> java :( – wook 2014-10-03 23:43:27

1

最後,他們都等於感謝pasimako把我的道路上。我不得不改變iv和salt轉換爲十六進制的方式,並且iv的長度和上面提到的keySize和iterationCount變量也是不確定的。

這裏是完整的工作代碼。

他們都應該輸出:

encypted:47S4kEkmEoMoOgngftzyFg ==

的Javascript

<script> 
var password = "password"; 
var salt = "3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55"; 

var plainText = "plaintext"; 
var iv = "123456789"; 

var key = CryptoJS.PBKDF2(password, CryptoJS.enc.Hex.parse(salt), {keySize: 128/32, iterations: 10}); 

var a = CryptoJS.AES.encrypt(plainText, key, {iv: CryptoJS.enc.Hex.parse(iv)}).ciphertext.toString(CryptoJS.enc.Base64); 


var result = "encypted: " + a + "<br \>"; 
document.getElementById("result").innerHTML = result; 
</script> 

的Java Main.class

public class main { 

public static void main(String[] args) throws Exception { 
    String result = Aes.encrypt("plaintext", "password", "3FF2EC019C627B945225DEBAD71A01B6985FE84C95A70EB132882F88C0A59A55", "123456789"); 
    System.out.println(result);  
} 
} 

的Java Aes.class

public class Aes { 
private static final int pswdIterations = 10; 
private static final int keySize = 128; 

public static String encrypt(String plainText, String password, String salt, String initializationVector) throws NoSuchAlgorithmException, NoSuchPaddingException, DecoderException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
      KeySpec spec = new PBEKeySpec(password.toCharArray(), Hex.decodeHex(salt.toCharArray()), pswdIterations, keySize); 
      SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); 
      cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(Hex.decodeHex(initializationVector.toCharArray()))); 
      byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes()); 
      return new Base64().encodeAsString(encryptedTextBytes); 
} 
}