【问题标题】:Converting .NET AES encryption to Java将 .NET AES 加密转换为 Java
【发布时间】:2014-02-19 19:45:40
【问题描述】:

我正在尝试编写一些 .NET 加密代码的 Java 等价物,以便他们可以通过 Web 服务解密我们的信息。

这是 .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);
    }

我遇到的第一个问题是弄清楚如何匹配密钥和 iv 的 PasswordDeriveBytes 事物,尽管我确信其余的都是错误的,但是步骤很简单。有谁知道如何匹配Java版本中的输出?

【问题讨论】:

  • 您确定您的 .NET 编码是硬 UTF-16 而不是 UTF-8?我将从调试和手动比较data 的字节内容开始。
  • 是的,我正在关注另一个问题的答案:stackoverflow.com/questions/4793387/…

标签: java .net encryption aes


【解决方案1】:

要匹配 java 中的 PasswordDeriveBytes,请使用 PasswordDeriveBytes(extending 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 中的 PasswordDeriveBytes 替换为 Rfc2898DeriveBytes。

要打印无符号字节(与 .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());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 2021-06-09
    相关资源
    最近更新 更多