【问题标题】:AES Encryption with java and WP7使用 java 和 WP7 进行 AES 加密
【发布时间】:2011-08-17 14:46:18
【问题描述】:

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

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

这是我们正在使用的代码:

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();
     }
}

任何帮助将不胜感激。

【问题讨论】:

  • 除此之外,不要使用message.getBytes() - 这将使用Java 中的平台默认编码。这可能不是问题,但无论如何这是个坏主意。
  • 看来,除了编码问题,你没有使用相同的密钥,相同的 IV,(而且可能也不相同的链接模式和相同的填充:我不知道您的 WP7 代码使用的默认值)。难怪他们给出的结果不一样。
  • 不要重用初始化向量 (IV)。它们必须为每条加密的消息随机生成。将随机 IV 与加密消息一起发送。这样,消息开头的相同部分的明文将不会总是产生相同的密文。这对安全很重要。

标签: c# java .net windows-phone-7 encryption


【解决方案1】:

请注意,在 Java 中,密码名称包含三个部分 - 算法、模式(CBC 与 ECB 等)和填充。您必须匹配所有三个,而不仅仅是算法。如果 WP7 不允许您明确指定模式和填充,请找出它们并在 Java 端进行匹配。

哦,请确保密钥相同。从例子中看不出来。

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

【讨论】:

  • 这可能是根本问题。我不久前遇到了这个问题——Java 和 .NET 有不同的默认链接模式 IIRC。
  • 大多数对称密码没有你所谓的trivial 密钥。
【解决方案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

【讨论】:

  • 嗨,埃里克森,谢谢它对我有用
猜你喜欢
  • 2014-01-14
  • 2016-03-15
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 2014-11-17
  • 2012-01-04
  • 1970-01-01
  • 2016-07-20
相关资源
最近更新 更多