2011-08-17 105 views
0

我們在Java中使用AES-128加密的代碼,我們希望在WP7中使用一些等效的代碼。使用java和WP7進行AES加密

然而,我們碰到一個問題:兩個實現產生不同的加密文本

這裏是代碼,我們使用:

Java代碼的

package com.emap.services; 
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; 
import java.security.InvalidAlgorithmParameterException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 

public class AESEcrypt1 { 

    static byte[] ibv = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 
     0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; 

    public String encryptData() { 
     String message = "Testing AES encryption-decryption amlgorithm for WP7."; 
     String encryptedStr = ""; 
     try { 
      SecretKeySpec skeySpec = new SecretKeySpec("Passkey".getBytes(), "AES"); 
      IvParameterSpec iv = new IvParameterSpec(ibv); 
      // Instantiate the cipher 
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
      cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv); 
      byte[] encrypted = cipher.doFinal(message.getBytes()); 
      encryptedStr = Base64.encode(encrypted); 
     } catch (BadPaddingException ex) { 
      System.out.println("Error: " + ex.getMessage()); 
      encryptedStr = "error"; 
     } catch (IllegalBlockSizeException ex) { 
      System.out.println("Error: " + ex.getMessage()); 
      encryptedStr = "error"; 
     } catch (InvalidAlgorithmParameterException ex) { 
      System.out.println("Error: " + ex.getMessage()); 
      encryptedStr = "error"; 
     } catch (InvalidKeyException ex) { 
      System.out.println("Error: " + ex.getMessage()); 
      encryptedStr = "error"; 
     } catch (NoSuchAlgorithmException ex) { 
      System.out.println("Error: " + ex.getMessage()); 
      encryptedStr = "error"; 
     } catch (NoSuchPaddingException ex) { 
      System.out.println("Error: " + ex.getMessage()); 
      encryptedStr = "error"; 
     } catch (Exception ex) { 
      System.out.println("Error: " + ex.getMessage()); 
      encryptedStr = "error"; 
     } 
     System.out.println("Encrypted: " + encryptedStr); 
     return encryptedStr; 
    } 
} 

WP7代碼

static byte[] ibv = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 
     0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}; 

public string Encrypt(string dataToEncrypt, string password) 
//public string Encrypt(string dataToEncrypt) 
{ 
    AesManaged aes = null; 
    MemoryStream memStream = null; 
    CryptoStream crStream = null; 
    try 
    { 
     //Generate a Key based on a Password and Salt  
     //Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt)); 
     Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, ibv);     
     aes = new AesManaged(); 
     aes.Key = rfc2898.GetBytes(aes.KeySize/8); 
     aes.IV = rfc2898.GetBytes(aes.BlockSize/8); 
     memStream = new MemoryStream(); 
     crStream = new CryptoStream(memStream, aes.CreateEncryptor(), CryptoStreamMode.Write); 
     byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt); 
     crStream.Write(data, 0, data.Length); 
     crStream.FlushFinalBlock(); 

     //Return Base 64 String     
     return Convert.ToBase64String(memStream.ToArray()); 
    } 
    finally 
    { 
     //cleanup     
     if (crStream != null) 
      crStream.Close(); 
     if (memStream != null) 
      memStream.Close(); 
     if (aes != null) 
      aes.Clear(); 
    } 
} 

任何幫助將不勝感激。

+4

除了別的以外,不要使用'message.getBytes()' - 它將使用Java中的平臺默認編碼。這可能不是問題,但無論如何這是一個壞主意。 –

+2

http://stackoverflow.com/questions/5295110/aes-encryption-in-java-and-decryption-in-c – BNL

+1

看來,除了編碼問題,你沒有使用相同的密鑰,相同的IV ,(也可能不是相同的鏈接模式和相同的填充:我不知道WP7代碼使用的默認值)。難怪他們不會給出同樣的結果。 –

回答

3

請注意,在Java中,密碼指定有三個部分 - 算法,模式(CBC vs. ECB等)和填充。你必須匹配所有三個,而不僅僅是算法。如果WP7不會讓你明確地指定模式和填充,請在Java端找出並匹配它們。

哦,並確保密鑰是一樣的。這個例子並不明顯。

編輯:調試填充問題,一個簡單的鍵是一個很大的幫助。也就是說,一個使算法發出明文副本作爲密文的密鑰。例如,對於RSA,它是公開指數1的那個。不確定對AES來說什麼是一個微不足道的關鍵 - 嘗試全零。

+0

這可能是潛在的問題。我碰到了這個問題 - Java和.NET有不同的默認鏈接模式IIRC。 – dotnetnate

+0

大多數對稱密碼不具有你稱之爲「微不足道」的密鑰。 –

2

它看起來不像你使用相同的密鑰。在Windows Phone 7實現中,您似乎正確地從密碼派生密鑰,而Java代碼不正確地直接使用某些密碼編碼。

See my previous answer有關Java中基於密碼的加密的一般概述。它將向您展示如何派生密鑰(根據RFC 2898中的PBKDF2),並描述了每個消息初始化向量的生成和交換。在後


JB Nizet's評論讓我在你如何使用ibv數據更仔細一看,他是正確的:你是不是在使用這兩個操作相同的IV。它被用作Java代碼中的IV,但在Windows代碼中,它被用作密鑰派生過程的「鹽」。這是兩個不同的目的,應該使用兩個不同的值。

由於ibv是一個固定值,它更適合於密鑰派生(每個密碼應該有一個唯一的鹽)。每條消息都應該有一個隨機選擇的新IV,並使用密文發送。在上面鏈接的Java示例中,您可以使用ibv作爲salt

+0

嗨erickson 感謝它爲我工作 –

相關問題