4

我做了很多研究,但我找不到我的问题的答案。我在 .NET 中进行 AES 加密(Rijndael 块大小 128 位),并在 Android (AES) 中使用相同的密码、salt 和 IV 进行解密。

C# 加密代码片段:

        byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
        byte[] saltValueBytes  = Encoding.ASCII.GetBytes(saltValue);

        byte[] plainTextBytes  = Encoding.UTF8.GetBytes(plainText);

        PasswordDeriveBytes password = new PasswordDeriveBytes(
                                                        passPhrase, 
                                                        saltValueBytes, 
                                                        hashAlgorithm, 
                                                        passwordIterations);

        byte[] keyBytes = password.GetBytes(keySize / 8);

        RijndaelManaged symmetricKey = new RijndaelManaged();

        symmetricKey.Padding = PaddingMode.PKCS7;

        symmetricKey.BlockSize = 128;  

        symmetricKey.Mode = CipherMode.CBC;        

        ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
                                                            keyBytes, 
                                                            initVectorBytes);

        MemoryStream memoryStream = new MemoryStream();        

        CryptoStream cryptoStream = new CryptoStream(memoryStream, 
                                                        encryptor,
                                                        CryptoStreamMode.Write);
        cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);

        cryptoStream.FlushFinalBlock();

        byte[] cipherTextBytes = memoryStream.ToArray();

        memoryStream.Close();
        cryptoStream.Close();

        string cipherText = Convert.ToBase64String(cipherTextBytes);

Android解密代码片段:

    KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), iterationCount); 

    SecretKey key = SecretKeyFactory.getInstance( 
            "PBEWithSHA1And128BitAES-CBC-BC").generateSecret(keySpec);

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");

    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));

    byte[] decrypted = cipher.doFinal(encrypted);

cipher.doFinal 调用引发以下异常。

“05-02 18:17:38.239: W/System.err(25547): javax.crypto.BadPaddingException: pad block 损坏”

我确实在 .NET 和 Android 中将填充设置为“PKCS7Padding”,并将加密块大小设置为 128 位。

但是,在 Android 中加密和在 Android 中解密可以正常工作。与 .NET 中的 Encrypt 和 .NET 中的 Decrypt 相同,也可以正常工作。

样品测试:

String PlainText            = "hello world";
String EncryptedDotNetblob  = "JyijoGEALMI25Zej7d+fMg==";
String EncryptedAndroidblob = "1HhuTQaLRJEK4zxI9FAO6A==";

如您所见,上面的 blob 也不同。

有人知道这里有什么问题吗?

4

2 回答 2

2

您派生的密钥不同,这就是您收到错误的原因(将它们记录为十六进制字符串以进行检查)。PasswordDeriveBytes另一方面,使用 PBKDF1 的修改版本SecretKeyFactory.getInstance("PBEWithSHA1And128BitAES-CBC-BC")为您提供了派生 PKCS#12 指定的密钥的密钥工厂。这些是不同的算法,并产生不同的密钥。Rfc2898DeriveBytes在 .NET 中使用并SecretKeyFactory .getInstance("PBKDF2WithHmacSHA1")使用相同的参数来获取相同的密钥。

于 2012-05-07T04:13:31.527 回答
-1

这是一个 C# 示例,您需要 IterationCount

protected void Page_Load(object sender, EventArgs e)
{
    string value = "";
    string password = "";
    string salt = "";
    string iv = "";


    byte[] vectorBytes = Convert.FromBase64String(Server.UrlDecode(iv)); 
    byte[] cipherText = Convert.FromBase64String(Server.UrlDecode(value));

    Rfc2898DeriveBytes key1 = new Rfc2898DeriveBytes(password, StringToByteArray(salt)); //same as PBKDF2WithHmacSHA1
    key1.IterationCount = 32;
    byte[] keyBytes = key1.GetBytes(16);

    string Answer = DecryptDataAES(cipherText, keyBytes, vectorBytes); //vectorBytes is good

    //litAnswer.Text = Answer;
}

public static string DecryptDataAES(byte[] cipherText, byte[] key, byte[] iv)
{
    string plaintext = null;

    using (Rijndael rijndael = Rijndael.Create())
    {
        rijndael.Key = key;
        rijndael.IV = iv;
        rijndael.Padding = PaddingMode.None;

        ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);

        // Create the streams used for decryption. 
        using (MemoryStream msDecrypt = new MemoryStream(cipherText))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                {
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }
    }
    return plaintext;
}

public static byte[] StringToByteArray(String hex)
{
    int NumberChars = hex.Length / 2;
    byte[] bytes = new byte[NumberChars];
    using (var sr = new StringReader(hex))
    {
        for (int i = 0; i < NumberChars; i++)
            bytes[i] =
              Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
    }
    return bytes;
}
于 2013-10-15T14:10:03.070 回答