2014-02-19 40 views
0

我正在嘗試編寫一些.NET加密代碼的Java等效代碼,以便他們可以通過web服務解密我們的信息。將.NET AES加密轉換爲Java

這裏是.NET方法:

public static string AESEncrypt(string text, string keyPhrase) 
    { 
     byte[] salt = { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }; 
     byte[] data = Encoding.Unicode.GetBytes(text); 
     PasswordDeriveBytes pdb = new PasswordDeriveBytes(keyPhrase, salt); 

     Rijndael algorithm = Rijndael.Create(); 
     algorithm.Key = pdb.GetBytes(32); 
     algorithm.IV = pdb.GetBytes(16); 

     MemoryStream mStream = new MemoryStream(); 
     CryptoStream cStream = new CryptoStream(mStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write); 
     cStream.Write(data, 0, data.Length); 
     cStream.Close(); 
     byte[] bytes = mStream.ToArray(); 

     return Convert.ToBase64String(bytes); 
    } 

這是我在Java版本失敗嘗試:

public static String encrypt(String text, String keyPhrase) throws Exception { 
     byte[] salt = { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }; 
     byte[] data = text.getBytes("UTF-16LE"); 
     PBEKeySpec spec = new PBEKeySpec(keyPhrase.toCharArray(), salt, 1); 

     SecretKey secret = new SecretKeySpec(keyPhrase.getBytes("UTF-16LE"), "AES"); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

     cipher.init(Cipher.ENCRYPT_MODE, secret); 
     byte[] ciphertext = cipher.doFinal(data); 
     return Base64.encodeBase64String(ciphertext); 
    } 

我已經是搞清楚如何匹配PasswordDeriveBytes事情的第一個問題關鍵和四,雖然我相信其餘的是錯誤的,但嬰兒的步驟。有誰知道如何匹配Java版本中的輸出?

+0

你確定你的.NET編碼是硬UTF-16而不是UTF-8?我首先調試並手工比較'data'的字節內容。 – chrylis

+0

是的,我正在從另一個問題的答案:http://stackoverflow.com/questions/4793387/utf-16-encoding-in-java-versus-c-sharp – user842800

回答

0

要匹配java中的PasswordDeriveBytes,請使用PasswordDeriveBytes(擴展org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator)from this stackoverflow answer

但是這隻適用於20字節以下的密鑰! 這是爲了生成密鑰的代碼:

String text="marcoS"; 
String keyPhrase="password123"; 
byte[] salt={ 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }; 

PasswordDeriveBytes generator = new PasswordDeriveBytes(new SHA1Digest()); 
generator.init(keyPhrase.getBytes("ASCII"), salt, 100); 
byte[] key = ((KeyParameter) generator.generateDerivedParameters(KeySize)).getKey();  

備選地,在與的dotNet Rfc2898DeriveBytes更換PasswordDeriveBytes。

要打印無符號(用於匹配.NET)字節使用:

private static void printByteArray(byte[] arr) { 
    if(arr == null || arr.length == 0){ 
     logger.debug("Array vuoto"); 
     return; 
    } 
    StringBuilder sb = new StringBuilder(); 
    for(byte b : arr) { 
     int x = b; 
     if(x<0){ 
      x+=256; 
     } 
     sb.append("["+x+"] "); 
    } 
    logger.debug(sb.toString()); 
}