2

我正在实现一个使用 128 位 Rijndael 加密请求所需的 web 服务客户端。因为 Silverlight 中不存在 RijndaelManaged 类,所以我遵循了此处的建议:此处已讨论过:AesManaged 和 RijndaelManaged

结果是我得到的结果是正确的(我的意思是,我使用 RijndaelManaged 得到的结果与前 32 个字符(128 位)相同),正好是块大小。我无法弄清楚我在这里做错了什么。我的 .Net 实现(RijndaelManaged)是这样的:

private static byte[] Encrypt(byte[] PlainTextBytes, byte[] KeyBytes, string InitialVector)
{
    byte[] InitialVectorBytes = Encoding.UTF8.GetBytes(InitialVector);
    RijndaelManaged SymmetricKey = new RijndaelManaged();
    SymmetricKey.Mode = CipherMode.ECB;
    SymmetricKey.Padding = PaddingMode.PKCS7;
    SymmetricKey.BlockSize = 128;
    ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
    MemoryStream MemStream = new MemoryStream();
    CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
    CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
    CryptoStream.FlushFinalBlock();
    byte[] CipherTextBytes = MemStream.ToArray();
    MemStream.Close();
    CryptoStream.Close();

    return CipherTextBytes;
}

而我的 Silverlight 是:

private string Encrypt(byte[] PlainTextBytes, byte[] KeyBytes, string InitialVector)
{
    AesManaged SymmetricKey = new AesManaged();
    byte[] InitialVectorBytes = SymmetricKey.IV;
    //NOTE- because Mode and Padding don't exist in AESManaged for Silverlight, I have to do the padding myself
    //for an empty InitalVector (which is my case)
    for (int i = 0; i < InitialVectorBytes.Length; i++) InitialVectorBytes[i] = 0;
    SymmetricKey.BlockSize = 128;
    ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
    MemoryStream MemStream = new MemoryStream();
    CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
    CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
    CryptoStream.FlushFinalBlock();
    byte[] CipherTextBytes = MemStream.ToArray();
    MemStream.Close();
    CryptoStream.Close();

    return CipherTextBytes;
}
4

2 回答 2

0

目前尚不清楚您是否真的在清除 IV。您将其作为字节数组获取,然后将其清除,但我不确定 IV 属性是否在返回之前复制内部值。我会用这个:

SymmetricKey.BlockSize = 128;
SymmetricKey.IV = new byte[SymmetricKey.BlockSize / 8];

(顺便说一下,我也会停止对参数和局部变量使用 PascalCase。通常的约定是对非常量变量使用 camelCase。)

编辑:示例代码演示您的代码如何并没有真正改变 IV:

AesManaged aes = new AesManaged();
byte[] iv = aes.IV;
iv[0] = 1;
iv[1] = 2;
Console.WriteLine(BitConverter.ToString(iv));      
Console.WriteLine(BitConverter.ToString(aes.IV));

样本输出:

01-02-01-1B-6E-05-B8-2A-C0-86-17-EF-A2-80-60-7B
D8-48-01-1B-6E-05-B8-2A-C0-86-17-EF-A2-80-60-7B

换句话说,改变数组中的值并没有真正改变 IV。

于 2011-03-18T17:21:18.617 回答
0

您的 .NET 版本对 AES 使用 EBC 模式,而 Silverlight 版本使用 CBC。第一个输出块在两个版本中是相同的,因为在 ECB 模式下不使用初始化向量,而在 CBC 模式下初始化向量为零。在 CBC 模式下,每个块与前一个块进行异或(第一个块与初始化向量进行异或),然后加密,而在 EBC 模式下,每个块都按原样加密。

于 2011-11-09T14:09:08.187 回答