AES加密与java和WP7

本文关键字:WP7 java 加密 AES | 更新日期: 2023-09-27 18:05:47

我们在Java中有AES-128加密的代码,我们希望在WP7中有一些等效的代码。

然而,我们遇到了一个问题:两种实现产生不同的加密文本

下面是我们使用的代码: <<p> Java代码/strong>
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;
    }
}
<<p> WP7代码/strong>
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();
     }
}

AES加密与java和WP7

请注意,在Java中,密码指定有三个部分——算法、模式(CBC vs. ECB等)和填充。你必须匹配这三者,而不仅仅是算法。如果WP7不允许您显式指定模式和填充,请找出它们并在Java端进行匹配。

哦,确保键是相同的。从例子中看不出来。

编辑:对于调试填充问题,一个微不足道的键是一个很大的帮助。也就是说,一个使算法发出其明文副本作为密文的密钥。以RSA为例,它的公共指数是1。

看起来不像你在使用相同的键。在Windows Phone 7的实现中,你似乎正确地从密码中获得密钥,而Java代码则不正确地直接使用密码的某些编码。

关于Java中基于密码的加密的一般概述,请参阅我之前的回答。它将向您展示如何派生密钥(根据RFC 2898中的PBKDF2),并描述正确的生成和每个消息初始化向量的交换。


JB Nizet对这篇文章的评论让我更仔细地观察了你是如何使用ibv数据的,他是对的:你在两次手术中都没有使用相同的静脉注射。它在Java代码中用作IV,但在Windows代码中,它被用作密钥派生过程的"盐"。这是两个不同的目的,应该使用两个不同的值。

由于ibv是一个固定值,因此更适合于密钥派生(每个密码应该有一个唯一的salt)。每条消息都应该有一个随机选择的新IV,并与密文一起发送。您可以在上面链接的Java示例中使用ibv作为salt