【问题标题】:Using RijndaelManaged encryption in Silverlight在 Silverlight 中使用 RijndaelManaged 加密
【发布时间】:2026-02-08 00:05:01
【问题描述】:

我正在实现一个使用 128 位 Rijndael 加密请求所需的 Web 服务客户端。因为 Silverlight 中不存在 RijndaelManaged 类,所以我遵循了这里的建议: 在这里讨论过:AesManaged and 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;
}

【问题讨论】:

    标签: silverlight-4.0 cryptography rijndaelmanaged webservices-client aes


    【解决方案1】:

    不清楚您是否真的在清除 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。

    【讨论】:

    • @Jon_Skeet 感谢提示,这不是问题,因为 Initial 向量稍后用于创建加密器,我得到的结果是相同的。无论如何感谢您的建议。
    • @magarcias:哪个初始向量呢?你以为是空的,还是实际上是空的?
    • @Jon_skeet 要么。我已经尝试设置初始向量和密钥,或者在 CreateEncryptor 调用中使用它们,或者按照您的建议初始化向量。所有选项都给出相同的结果,显然这些是等效的: SymmetricKey.Key = KeyBytes; SymmetricKey.IV = InitialVectorBytes; ICryptoTransform 加密器 = SymmetricKey.CreateEncryptor();和: ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
    • @margarcias:是否将 InitialVectorBytes 设置为一个零初始化数组? (顺便说一句,如果您遵循正常的 .NET 命名约定,您的代码仍然会更清晰。)
    【解决方案2】:

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

    【讨论】: