【问题标题】:Why does any length key work for RijndaelManaged?为什么任何长度密钥都适用于 RijndaelManaged?
【发布时间】:2015-12-17 20:17:09
【问题描述】:

关于方法...

RijndaelManaged.CreateDecryptor Method (Byte[], Byte[])

Here 它说的是第一个参数...

用于对称算法的密钥。密钥大小 必须是 128、192 或 256 位。

但我可以将密钥设置为任意长度的字符串...

var key = Encoding.UTF8.GetBytes("whetever...");

为什么不对字节数组的长度更挑剔?以及它如何确定使用三个密钥长度中的哪一个?

【问题讨论】:

  • 但是最好提供key和iv的全长,不要依赖padding。
  • 使用字符串作为密钥通常是个坏主意,它会大大削弱您的保护。使用像Rfc2898DeriveBytes 这样的“密钥派生函数”,您将密码+ 盐输入其中,它可以让您获得一个随机的byte[],您可以将其输入密钥。它的作用是每次都会为您提供相同的byte[] 相同的密码和盐。
  • 但是密码不是字符串吗? A 我会在哪里存放盐?我不是已经用初始化向量(第二个参数)实现了同样的目标吗?
  • 因为微软搞砸了参数验证。

标签: c# .net cryptography rijndaelmanaged


【解决方案1】:

并非任何密钥大小都有效。只应允许一组特定的密钥大小。

RijndaelManagedLegalKeySizes 大小属性实际上报告了以下值:

MinSize = 128
MaxSize = 256
SkipSize = 64

这应该表明只支持 AES 密钥大小:128、192,当然还有 256。这基本上意味着 RijndaelManaged 没有完全实现 Rijndael,它也允许 160 和 224 位作为密钥大小。实际上,我认为它也不允许 160 和 224 位的块大小。

现在你的问题给我带来了一些问号,所以我决定查看哪些密钥大小实际上被接受而不引发异常,我得到了以下令人惊讶的结果:

8, 9, 10, 11, 12, 13, 14, 15, 16, 24, 32

或者,以位而不是字节为单位:

64, 72, 80, 88, 96, 104, 112, 120, 128, 192, 256

所以RijndaelManaged 似乎接受了比指定更多的密钥大小,并且这些额外的密钥大小低于类和 Rijndael 算法指定的最小长度

现在让我们用这些无效的密钥大小加密一些东西:

064 : 1903b797b48ce006e618cb605d356981cc9b231195420010916e449037d3ac5b
072 : 1903b797b48ce006e618cb605d356981cc9b231195420010916e449037d3ac5b
080 : 1903b797b48ce006e618cb605d356981cc9b231195420010916e449037d3ac5b
088 : 1903b797b48ce006e618cb605d356981cc9b231195420010916e449037d3ac5b
096 : 4002ae70943dafdec10d4fbe2f97dc95b0a61e7412277197623b6d3d3e0da31c
104 : 4002ae70943dafdec10d4fbe2f97dc95b0a61e7412277197623b6d3d3e0da31c
112 : 4002ae70943dafdec10d4fbe2f97dc95b0a61e7412277197623b6d3d3e0da31c
120 : 4002ae70943dafdec10d4fbe2f97dc95b0a61e7412277197623b6d3d3e0da31c
128 : 66e94bd4ef8a2c3b884cfa59ca342b2e9434dec2d00fdac765f00c0c11628cd1
192 : aae06992acbf52a3e8f4a96ec9300bd71045be567103016ac50b21b86fc5457e
256 : dc95c078a2408989ad48a21492842087f3c003ddc4a7b8a94baedffc3d214c38

注意:对于那些感兴趣的人:密钥由全零、明文和 IV 组成的 CBC 也只有 16 个字节设置为零。在 Windows 10 上进行了测试:

操作系统:Microsoft Windows NT 10.0.10240.0,CLR:4.0.30319.42000

因此,对于密钥大小 64、72、80、88、96、104、112、120,您只会得到一些无效的、未指定的结果。查看代码,它基本上只使用 8 个字节作为密钥,而将其他字节设置为对于密钥大小 8..11 和 12 字节作为密钥大小为 12..15 的密钥为零。在这种情况下,块大小将为 128 位,否则块大小将与密钥大小相同。因此,对于 72、80、88、104、112 和 120 位的密钥,实现实际上会在密钥使用之前从密钥末尾剥离一到三个字节

所以基本上这似乎是实现中的一个错误。基本上你不应该在LegalKeySizes返回的值之外使用RijndaelManaged


如前所述,您应该使用Rfc2898DeriveBytes 将密码转换为具有有效密钥大小的密钥。

【讨论】:

  • 几个月前我挖掘了那个代码。据我所知,它将密钥填充到完整的 32 位字,并根据字数调整密钥时间表/轮数。
  • 你知道填充的类型吗?好像前端只会生成一个大小的key,所以可能不需要调整轮数/key schedule..
  • 天哪,它没有填充,它会剥离字节。
  • 我不记得细节,但我记得被代码吓坏了。它甚至可能包含某些键大小的缓冲区溢出(由运行时检查数组索引捕获)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 2020-05-08
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
相关资源
最近更新 更多