java 每条消息都需要 Cipher.init() 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13071489/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cipher.init() required for each message?
提问by davidkomer
Assume two clients are exchanging secure messages back and forth.
假设两个客户端来回交换安全消息。
Must this block be run every time for each message, or can any step(s) be done just once at start:
必须每次都为每条消息运行此块,或者可以在开始时只执行一次任何步骤:
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(content);
I guess to lend some context- although I don't (yet) understand the internals completely, it is my understanding that for security purposes it's important to change the IV for each message. So I think the answer to this question will depend on whether that step happens under the hood at the doFinal() stage or init()....?
我想提供一些上下文 - 尽管我(还)不完全了解内部结构,但我的理解是,出于安全目的,更改每条消息的 IV 很重要。所以我认为这个问题的答案将取决于该步骤是在 doFinal() 阶段还是 init() 阶段发生在幕后?...?
采纳答案by imichaelmiers
You are correct: to be safe you need to use a new,random, IV for each message. This means you either need to recreate the cipher or randomly set the IV yourself for each subsequent message. The former is probably safer since if you change ciphers or modes, there maybe some other state you need to randomly set as well and reinitializing the cipher should handle all of it.
你是对的:为了安全起见,你需要为每条消息使用一个新的、随机的 IV。这意味着您要么需要重新创建密码,要么自己为每个后续消息随机设置 IV。前者可能更安全,因为如果您更改密码或模式,您可能还需要随机设置一些其他状态,并且重新初始化密码应该可以处理所有这些。
If you don't do this, you end up with the same rather bad bug SSL had with IV reuse.
如果您不这样做,您最终会遇到 SSL 与 IV重用相同的相当糟糕的错误。
Cipher.doFinal does not reset the cipher to a random IV. In fact, its far worse than that, it appears to reset the internal state to the same IV you started with. As shown by this code.
Cipher.doFinal 不会将密码重置为随机 IV。事实上,它远比这更糟糕,它似乎将内部状态重置为与您开始时相同的 IV。如这段代码所示。
Cipher f = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
f.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = f.getIV();
System.out.println(Arrays.toString(f.doFinal("hello".getBytes())));
System.out.println(Arrays.toString(f.getIV()));
System.out.println(Arrays.toString(f.doFinal("hello".getBytes())));
System.out.println(Arrays.toString(f.getIV()));
System.out.println( Arrays.equals(f.getIV(), iv)); // true