使用无效密钥解密并不总是抛出 CryptographicException

Posted

技术标签:

【中文标题】使用无效密钥解密并不总是抛出 CryptographicException【英文标题】:Decryption with invalid key not always throws CryptographicException 【发布时间】:2015-01-14 14:52:13 【问题描述】:

我正在为我的加密服务使用以下设置

        var cipher = new RijndaelManaged();
        cipher.KeySize = 256;
        cipher.BlockSize = 256;
        cipher.Padding = PaddingMode.ISO10126;
        cipher.Mode = CipherMode.CBC;
        cipher.Key = _key;
        return cipher;

为了我的服务,我编写了一个测试,它试图用无效的密钥解密加密数据。

    [Test]
    public void EncryptDecrypt_UsingInvalidKey_ShouldThrowCryptographicException()
    
            var testInput = new TestInput();
            var encriptedData = _service.Encrypt(testInput.Input);
            var decrtryptServiceWithNewKey = GetService();

            Assert.Throws<CryptographicException>(() => decrtryptServiceWithNewKey.Decrypt(encriptedData));

    

问题是有时这个测试会失败,因为它没有抛出我预期的 CryptographicException(填充无效并且无法删除。)。

Initial Encryption Key :d/Ww5u5V/dV4FzYaFp8QEKeikFEFxaK9Z9ZBER1/y5A=

case 0) try decrypt with key :2pPmUsE4Erk+kUQPnmDCBzVlvvvePIjGJpi3cacJy1U=
                          iv :Hi4GbhuSKR5UUTyCgO+VNb/jQ+U1SfxXPPiAgiyCRhM=

  1)   key :40IeO1ZJF6miVFfmEaTkJDCus/EeiWBzzFqhvlxg/Js=
        iv :B535OzpMErNeSVeR98q5YEIikh0juk9YIsOBWop/N0I=
                                              Test pass

  2)   key :d1M0Mq4/5JIcp5oF8nvfj1e8hHv5uo0zSMf820ThnkM=
        iv :LAGLmg0LORGpHRWMKw3myPzuUjqlH4urn4+iMl248CE=
                                              Test pass

  3)   key :jDJdtNBUHe0CeNwf4VdyqpdMOAiDBFYZ0XJIXjw9BOw=
        iv :bCzj4E2jFkb3CRY5J6K1YjzsEBSn2ULjHNXtbZIbk2o=
                                              Test pass

  4)   key :zCbD4krNVS1wg8kjcW4+B7esMeJhCFK3PrlMrphpC0s=
        iv :rjLqP2L52KKu09tzJEuuIV9vRxpURI/Fz0R9vmOjsw8=

 Expected: <System.Security.Cryptography.CryptographicException>
 But was:  null

您能否说明为什么在某些情况下我的测试中无法得到 CryptographicException?

【问题讨论】:

【参考方案1】:

问题在于解密后的明文大约有八次正确的填充。当解密的明文以0120 结尾时,就会发生这种情况。 256 / 32 字节的块大小为该特定范围提供了有效的填充。

不应该使用填充来验证密文/明文的正确性。这样做甚至是危险的,因为它可能导致填充预言机攻击。相反,您应该在密文上使用(H)MAC - 将身份验证标签添加到密文。 MAC 应该使用不同的密钥并且还应该包括 IV。也可以使用现代认证密码,例如 GCM,它允许使用相同的密钥 - GCM/CCM/EAC 等已经在 authentication tag 中包含 IV。

CBC 模式加密独立只能用于机密性,并且只有在填充/明文 oracle 攻击不适用时(即永远不应该使用它原样 > 在传输协议中)。需要一个身份验证标签来添加完整性(您当前正在尝试测试的内容)和真实性。

请注意,ISO10126 已过时,并且块大小为 256 位的 Rijndael 不是 AES。所以你目前没有使用任何标准化的加密货币。

【讨论】:

以上是关于使用无效密钥解密并不总是抛出 CryptographicException的主要内容,如果未能解决你的问题,请参考以下文章

创建 azure vm 时,terraform 抛出“无效或未知的密钥:区域”

Android KeyStore - 密钥并不总是持久的

Tomcat 9 无效的密钥库密码

如何修复无效的 AES 密钥长度?

如果我用随机密钥加密字符串,如何解密它

用于加密的公钥;用于解密的私钥?