在没有良好随机源的情况下生成初始化向量
对于 Rockbox 的密码存储插件(用 C 编写),我需要生成初始化向量。
问题是我没有好的随机性来源。 Rockbox 提供的 random() 不是加密 RNG。而且我几乎没有任何可以访问的随机源(没有鼠标移动,......在运行 Rockbox 的 iPod 上)。
目前,密钥是通过 PBKDF2 从用户提供的密码和盐(这是一个常量前缀 + random() 中的一些数据)派生出来的。我认为伪随机数据对于 PBKDF2 10000 次迭代的盐来说应该足够好了。
但是,我从哪里获取初始化向量呢?如果我获取一些半随机数据(时间 + random())和 SHA,例如 10000 次,可以吗?我应该使用 arc4random 和从 random() 获取的种子吗?
如果我实际上从不使用同一个密钥两次(每次存储的数据更改时都会重新计算盐),我是否还需要 IV?处理此类情况的最佳方法是什么?
编辑: 只有一个用户(我,拥有 iPod),加密算法:AES-CBC 256 位。 该文件仅存储各个网站的站点/帐户/密码列表。它很少被修改(每当我在网站上创建一个新帐户时),当发生这种情况时,会生成新的盐和新的 IV。
For a password storing plugin (written in C) for Rockbox I need to generate initialization vectors.
The problem is that I don't have a good source of randomness. The Rockbox-supplied random() is not a cryptographic RNG. And I've got hardly any sources of randomness I can access (no mouse movements, ... on an IPod running Rockbox).
The key is currently derived via PBKDF2 from a user-supplied password and a salt (which is a constant prefix + some data from random()). I think the pseudo-random data should be good enough for a salt with 10000 iterations of PBKDF2.
However, where do I take my initialization vector from? Is it OK if I take some semi-random data (time + random()) and SHA that, say, 10000 times? Should I take arc4random with a seed taken from random()?
Do I even need an IV if I effectively never use the same key twice (the salt is recomputed every time the stored data is changed)? What's the best way to deal with situations like these?
Edit:
Just a single user (me, owning the IPod), encryption algorithm: AES-CBC 256 bit.
The file just stores a site/account/password list for various websites. It is rarely modified (whenever I create a new account on a website), when that happens a new salt and a new IV is generated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一般来说,对于 CBC,IV必须是随机且均匀的。 “不重复”还不够。更准确地说,CBC 的重点是避免同一个数据块被馈送到底层分组密码两次的情况。因此,条件是如果您使用相同的密钥加密两个消息,则两个 IV 的差异必须是均匀随机的。对于 AES 等 128 位分组密码,获得相同分组两次的概率足够低,可以忽略不计——只要 IV 是在整个 128 位值空间上以均匀概率随机选择的。 IV 选择中的任何结构(例如重复使用相同的 IV、使用计数器或低质量随机生成器)都会增加该概率,因为您正在加密本身具有很多结构的数据。
这有一个好的一面:如果您从不使用同一个密钥两次,那么您可以容忍固定的 IV。但这是一个强烈的“从不”。
“非重复 IV”对于 CBC 来说并不是一个足够好的属性。然而,有一些加密模式可以使用非重复IV。特别是,请查看 EAX 和 GCM。这里的技巧是这些模式在使用加密密钥的自定义 PRNG 中使用提供的 IV;这将非重复 IV(例如计数器或低质量的“随机值”)转换为从密码学角度来看看起来足够随机的东西。不要尝试构建自己的 PRNG!这些事情很微妙,没有确定的方法来测试结果的质量。
Generally speaking, with CBC, the IV MUST be random and uniform. "Non-repeating" is not sufficient. To be more precise, the whole point of CBC is to avoid the situation where the same data block is fed twice to the underlying block cipher. Hence, the condition is that if you encrypt two messages with the same key, then the difference of the two IV must be uniformly random. With a 128-bit block cipher such as the AES, the probability that the same block is obtained twice is sufficiently low as to be neglected -- as long as the IV is randomly chosen with uniform probability over the whole space of 128-bit values. Any structure in the IV selection (such as reusing the same IV, using a counter, or a low-quality random generator) increases that probability, because you are encrypting data which has itself a lot of structure.
There is a bright side to that: if you never use the same key twice, then you can tolerate a fixed IV. But that is a strong "never".
"Non-repeating IV" is not a good enough property with CBC. However, there are some encryption modes which can use non-repeating IV. In particular, have a look at EAX and GCM. The trick here is that those mode use the provided IV in a custom PRNG which uses the encryption key; this transform the non-repeating IV (e.g. a counter, or a "random value" of low quality) into something which, from a cryptographic point of view, looks random enough. Do not try to build your own PRNG ! These things are subtle and there is no sure way to test the quality of the result.
IV 不需要是随机的,它只需要对于给定的密钥和数据对来说是唯一的(假设我们正在讨论 CBC 的 IV)。
所以 random() 应该可以用于此目的。
The IV does not need to be random, it just needs to be unique for a given pair of key and data (assuming we are talking about an IV for CBC).
So random() should be okay for this purpose.
好消息!初始化向量不需要是随机的,只需对于每个加密都不同即可。所以你可以使用用户名作为盐。如果您同时使用用户名和时间,那么攻击者将无法检测到密码重用。
GREAT NEWS! The initialization vector doesn't need to be random, it just needs to be different for every encryption. So you can use the user's name as the salt. If you use both the user's name and the time then an attacker won't be able to detect password reuse.