我使用以下设置进行加密服务
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?
答案 0 :(得分:1)
问题在于解密的明文大约有八次正确填充。当解密的纯文本以01
结尾为20
时会发生这种情况。块大小为256/32字节,可以为该特定范围提供有效的填充。
绝不应使用填充来验证密文/明文的正确性。这样做甚至是危险的,因为它可能导致填充oracle攻击。相反,您应该在密文上使用(H)MAC - 向密文添加身份验证标记。 MAC应使用不同的密钥,并且还应包括IV。也可以使用现代经过验证的密码,例如GCM,它允许使用相同的密钥 - GCM / CCM / EAC等已经包含身份验证标记中的IV 。
CBC模式加密在它自己的上只能用于机密性,并且只有当padding / plaintext oracle攻击不适用时(即它永远不应该像那样使用 >在传输协议中)。需要使用身份验证标记来添加完整性(您当前正在尝试测试的内容)和真实性。
请注意,ISO10126已过时,块大小为256位的Rijndael不是AES。所以你现在没有使用任何标准化的加密。