如何为AES / CTR / NoPadding选择合适的IV(初始化向量)? [英] How to pick an appropriate IV (Initialization Vector) for AES/CTR/NoPadding?

查看:2906
本文介绍了如何为AES / CTR / NoPadding选择合适的IV(初始化向量)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想加密由webapp编写的cookie,我想将cookies的大小保持在最低限度,因此我选择了AES / CTR / NoPadding。

I would like to encrypt the cookies that are written by a webapp and I would like to keep the size of the cookies to minimum, hence the reason I picked AES/CTR/NoPadding.

你建议使用什么作为IV,这是随机的,仍然保持应用无状态。我知道我可以生成一个随机的IV并将其附加到消息中,但这会增加cookie的大小。

What would you recommend to use as IV that's random enough and still keep the app stateless. I know that I can just generate a random IV and append it to the message, but that will increase the size of the cookie.

另外,建议的大小是IV为128位AES?

In addition, what's the recommended size of IV for 128-bit AES?

大家还在做什么?是否存在尝试和真实的方式?我不想重新发明。

How else is everyone doing this? Do any "tried and true" ways exist? I don't want to reinvent the wheel.

推荐答案

CTR安全性要求您永远不要重复使用IV用于具有相同密钥的两个消息加密。实际上甚至更严格:CTR模式通过加密计数器的连续值(IV只是该计数器的初始值)工作,只有当相同的计数器值不使用两次时才能实现适当的安全性;这意味着使用IV加密值实际上消耗一系列连续的IV值,这些序列不能再与另一个加密一起使用。

CTR security requires that you never reuse an IV for two message encryptions with the same key. Actually it is even stricter: CTR mode works by encrypting successive values of a counter (the IV is just the initial value for that counter) and proper security is achieved only if the same counter value is not used twice; this means that encrypting a value with an IV actually "consumes" a sequence of successive IV values which must not be reused with another encryption.

简单的方法是使用密码安全的随机数生成器,并为每个消息创建一个新的16字节随机IV。我强调加密安全,因为这是进口;一个基本的随机数发生器是不够的。使用Java,使用 java.util.SecureRandom 。使用Win32,调用 CryptGenRandom()。通过随机选择,可能的128位IV的空间足够大,使得碰撞极不可能。实际上,这就是为什么AES使用128位块(因此意味着128位IV)。

The easy way to do that is to use a cryptographically secure random number generator, and create a new 16-byte random IV for every message. I underline "cryptographically secure" because that's import; a basic random number generator is not enough. With Java, use java.util.SecureRandom. With Win32, call CryptGenRandom(). With a random selection, the space of possible 128-bit IV is large enough that collisions are extremely improbable. Actually, that's why AES uses 128-bit blocks (thus implying 128-bit IV).

解密消息的实体必须知道IV,所以你必须将其与加密消息一起存储。这是一个额外的16个字节。我明白,这个开销是你想要避免的,虽然16个字节不是一个cookie。 cookie的有效最大长度取决于Web浏览器,但是4000个字符似乎在无处不在中工作。一个16字节的四进制字符(例如使用Base64编码)将使用大约22个字符,即大大小于最大cookie大小的1%:也许你能负担得起?

The entity which will decrypt the message must know the IV, so you have to store it along with the encrypted message. That's an extra 16 bytes. I understand that this overhead is what you want to avoid, although 16 bytes is not that much for a cookie. The effective maximum length of a cookie depends on the Web browser but 4000 characters appear to work "everywhere". A 16-byte IV, when encoded in characters (e.g. with Base64), will use about 22 characters, i.e. much less than 1% of your maximum cookie size: maybe you can afford that ?

现在我们可以通过诡计来尝试减少IV长度:

Now we can get funky and try to reduce the IV length through trickery:


  • 生成IV具有散列函数:服务器端,使用从0开始的计数器,每次需要新的IV时都会递增。要得到IV,你用适当的散列函数对计数器进行散列,例如SHA-256,并保留哈希值的前16个字节。散列函数的随机化属性将足以使IV对于CTR要求足够随机。这需要一个加密安全的散列函数,因此SHA-256(避免MD5)。然后,您只需将计数器值存储在cookie中,计数器将短于16个字节(例如,如果您的客户数量不超过4亿,计数器将以4个字节为准)。然而,有一个隐藏的成本:服务器(我认为服务器在你的系统中执行加密)必须确保它不会重复使用计数器值,所以它必须以一种持续存在的方式存储当前计数器服务器重新启动,如果您扩展到几个前端也不会失败。这似乎并不容易。

  • Generate the IV with a hash function: server-side, use a counter, which begins at 0 and is incremented every time a new IV is needed. To get the IV, you hash the counter with a suitable hash function, e.g. SHA-256, and you keep the first 16 bytes of the hash value. The "randomization properties" of the hash function will be enough to make the IV sufficiently random with regards to CTR requirements. This needs a cryptographically secure hash function, hence SHA-256 (avoid MD5). You then just have to store the counter value in the cookie, and the counter will be shorter than 16 bytes (e.g. if you have no more than 4 billions customers, the counter will fit in 4 bytes). However, there is a hidden cost: the server (I suppose the server is performing the encryption in your system) must make sure that it never reuses a counter value, so it must store the "current counter" somewhere in a way which persists over server reboots, and also does not fail if you scale up to several front-ends. That's not as easy at is seems.

可能使用外部唯一值,cookie可能是上下文的一部分提供足够的数据来生成每个加密唯一的值。例如,如果请求还包含(清除)用户ID,则可以将用户ID用作IV源。该设置与上述相似:您获取所有数据,将其填入SHA-256,SHA-256输出的前16个字节是您需要的IV。这只有在给定的加密消息的数据没有变化的情况下才能起作用,如果它真的是唯一的。这是一个罕见的情况:例如,只有在永远不需要为同一用户重新加密新消息的情况下,用户ID才是有用的,如果永远不会有用户ID被重用的可能性(例如,一个旧的用户退出,一个新的用户来到并选择现在的免费用户ID)。

Use an external unique value: possibly, the cookie could be part of an context which provides enough data to generate a value which will be unique to each encryption. For instance, if the request also contains (in the clear) a "user ID", you could use the user ID as an IV source. The setup is similar to the one above: you get all that data, stuff it into SHA-256, and the first 16 bytes of SHA-256 output is the IV you need. This works only if that data does not change for a given encrypted message, and if it is really unique. This is a rare occurrence: for instance, a "user ID" is good for that only if there is never a need to reencrypt a new message for the same user, and if there is never a possibility that a user ID is reused (e.g. an old user quits, a new user comes and selects the now free user ID).

使用加密安全PRNG生成的字节IV仍然是安全的方式,我推荐的方式。如果您在cookie中找到空格,那么这意味着您正在接近4 kB的限制,此时您可能需要使用压缩(在加密之前的数据上;加密后,压缩非常非常不可能工作)。使用 zlib (在Java中,您可以通过 java.util.zip )。

Using a random 16-byte IV generated with a cryptographically secure PRNG is still the "safe" way, and the one I recommend. If you find space tight in the cookie, then this means that you are approaching the 4 kB limit, at which point you may want to use compression (on the data before encryption; after encryption, compression is very very unlikely to work). Use zlib (in Java, you can access zlib through java.util.zip).

警告:在上述所有内容中,我不是说任何关于cookie是否加密确实有助于提供您尝试实现的任何安全特性。通常,当需要加密时,实际上需要加密和完整性,然后应该使用组合加密和完整性模式。查找 GCM CCM 。此外,cookie加密主要是为了一个目的,这是为了避免存储服务器端一点用户特定数据的成本。如果你想加密一个cookie的其他东西,例如要认证有效的用户,那么你做错了:加密不是正确的工具。

Warning: in all of the above, I am not saying anything about whether cookie encryption does help in providing whatever security characteristics you are trying to achieve. Usually, when encryption is needed, you actually need both encryption and integrity, and then you should use a combined-encryption-and-integrity mode. Lookup GCM and CCM. Moreover, cookie encryption is mostly good for one purpose, which is to avoid the cost of storing server-side a bit of user-specific data. If you want to encrypt a cookie for something else, e.g. to authenticate a valid user, then you are doing it wrong: encryption is not the right tool for that.

这篇关于如何为AES / CTR / NoPadding选择合适的IV(初始化向量)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆