RijndaelManaged 施工期间的奇怪行为

Posted

技术标签:

【中文标题】RijndaelManaged 施工期间的奇怪行为【英文标题】:Strange behaviour during RijndaelManaged construction 【发布时间】:2016-11-25 20:29:25 【问题描述】:

我在以下代码中注意到以下奇怪的行为,如果我在对象初始化程序中设置 Key,它会生成一个随机密钥并且不会设置我的密钥。这是一个故障吗?

var algorithm = new RijndaelManaged

    Mode = CipherMode.CBC,
    Key = keyBytes,        //if i set the keyBytes here
    KeySize = _keySize,
    IV = Encoding.ASCII.GetBytes(_initVector),
    BlockSize = 128,
    Padding = PaddingMode.Zeros
; // Set encryption mode to Cipher Block Chaining   

bool wtf= algorithm.Key.AreEqual(keyBytes);

if (!wtf) // <!-- the Key is not the same here

    algorithm.Key = keyBytes; // so i end up having to set it again here so that i can decrypt properly

【问题讨论】:

【参考方案1】:

这不是错误。看源码

这是 Key 属性。

    public virtual byte[] Key 
        get  
            if (KeyValue == null) GenerateKey();
            return (byte[]) KeyValue.Clone();
        
        set  
            if (value == null) throw new ArgumentNullException("value");
            Contract.EndContractBlock();
            if (!ValidKeySize(value.Length * 8))
                throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize"));

            // must convert bytes to bits
            KeyValue = (byte[]) value.Clone(); // your byte[] will be set
            KeySizeValue = value.Length * 8;   // key size will be set too
        
    

这是 KeySize 属性。

public virtual int KeySize 
    get  return KeySizeValue; 
    set 
        if (!ValidKeySize(value))
            throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize"));

        KeySizeValue = value;
        KeyValue = null; // here keyvalue becomes null
    

那是因为您在设置KeyValue 之后设置了KeySize,因此您遇到了问题。

我认为你不应该设置KeySize,因为它会自动设置,正如你在源代码中看到的那样。如果你设置了KeySize,你的Key 会因为任何原因而变为空。

var algorithm = new RijndaelManaged
        
            Mode = CipherMode.CBC,
            Key = keyBytes,
            // KeySize = _keySize, // remove this
            IV = Encoding.ASCII.GetBytes(_initVector),
            BlockSize = 128,
            Padding = PaddingMode.Zeros
        ; 

【讨论】:

我想根据定义这不是一个错误..但我仍然觉得这是一个奇怪的实现。如果不进行反思,您永远不会想到会发生这种情况。它违反了对象初始化的规则。再加上让一个财产秘密地使另一个财产无效,这感觉很肮脏。 因为这些属性是public virtual,您可以创建自己的类,从RijndaelManaged 继承并覆盖KeyKeySize。但我会首先寻找它以这种方式实施的原因。可能与 KeyValue 不同的 KeySizeValue 会引入一些其他错误甚至运行时错误等。@drowhunter 是的,但它引出了一个问题..如果键数组和键大小需要匹配,为什么甚至允许它们设置不同?对我来说似乎逻辑很糟糕。

以上是关于RijndaelManaged 施工期间的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

RijndaelManaged .NET Framework 和 .NET Core 的区别

AesManaged 与 RijndaelManaged [关闭]

为啥我不能使用 RijndaelManaged 解密数据?

algorithm - C# 中的 RijndaelManaged 类是不是等同于 AES 加密?

使用 CryptDecrypt 解密 RijndaelManaged 加密字符串

让 .NET 中的 SlowAES 和 RijndaelManaged 类一起玩