2011-08-17 69 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 感谢它为我工作 –

相关问题