Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = cipher.getIV(); // ?????
该IV是否满足“对于给定的密钥,IV不得重复”的要求。来自RFC 4106?
我也非常感谢对我相关问题的任何回答/洞察力(见下文),但第一个问题是最困扰我的。我不知道在哪里可以找到源代码或文档来回答这个问题。
下面是大致的完整代码。如果我在写这篇文章时引入了错误,我深表歉意:
class Encryptor {
Key key;
Encryptor(byte[] key) {
if (key.length != 32) throw new IllegalArgumentException();
this.key = new SecretKeySpec(key, "AES");
}
// the output is sent to users
byte[] encrypt(byte[] src) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = cipher.getIV(); // See question #1
assert iv.length == 12; // See question #2
byte[] cipherText = cipher.doFinal(src);
assert cipherText.length == src.length + 16; // See question #3
byte[] message = new byte[12 + src.length + 16]; // See question #4
System.arraycopy(iv, 0, message, 0, 12);
System.arraycopy(cipherText, 0, message, 12, cipherText.length);
return message;
}
// the input comes from users
byte[] decrypt(byte[] message) throws Exception {
if (message.length < 12 + 16) throw new IllegalArgumentException();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec params = new GCMParameterSpec(128, message, 0, 12);
cipher.init(Cipher.DECRYPT_MODE, key, params);
return cipher.doFinal(message, 12, message.length - 12);
}
}
>
用cipher.getiv()返回的IV对我来说以这种方式使用安全吗?
cipher.getiv()
并使用自己的计数器自己构造一个IV?cipher.getiv()
的源代码是否可以在线获得,假设我使用的是Oracle JDK 8+JCE无限强度扩展?IV总是12字节长吗?
身份验证标记是否总是16字节(128位)长?
使用#2和#3,并且缺少填充,这是否意味着我的加密消息总是12+src.length+16
字节长?(这样我就可以安全地将它们压缩成一个字节数组,我知道它的正确长度?)
在给定用户知道的恒定src数据的情况下,我向用户显示无限数量的src数据加密是否安全?
(因为这些问题都是关于我自己的代码的同一块的,而且它们彼此之间有很强的相关性,而其他人在实现相同的功能时可能/应该有相同的问题集,所以把这些问题拆分成多个帖子感觉是不对的。如果这对StackOverflow的格式更合适的话,我可以分别重新发布它们。让我知道!)
Q1:Cipher.getiv()返回的IV对我来说以这种方式使用安全吗?
是的,至少对于Oracle提供的实现来说是这样。它是使用默认的securerandom
实现单独生成的。由于它的大小为12字节(GCM的默认值),所以您有96位的随机性。反面重复的几率非常小。您可以在Oracle JDK所基于的OpenJDK(GPL'ed)中查找源代码。
然而,我仍然建议您生成自己的12个随机字节,因为其他提供者的行为可能不同。
Q2:IV总是12字节长吗?
这是很有可能的,因为它是GCM默认值,但其他长度对GCM是有效的。然而,该算法必须对12字节以外的任何其他大小进行额外的计算。由于存在缺陷,强烈建议将其保持在12字节/96位,API可能会限制您选择IV大小。
Q3:身份验证标记总是16字节(128位)长吗?
不,它可以有任何大小的字节,范围从64位到128位,递增8位。如果它较小,它只是由身份验证标记的最左边的字节组成。您可以使用GCMParameterSpec
作为Init
调用的第三个参数指定另一个大小的标记。
注意,GCM的强度很大程度上取决于标签的大小。我建议保持128位。96位应该是最小值,特别是如果您想生成大量的密文。
Q4:使用#2和#3,并且缺少填充,这是否意味着我的加密消息总是12+src.length+16字节长?(这样我就可以安全地将它们压缩成一个字节数组,我知道它的正确长度?)
见上文。对于Oracle提供程序,情况就是这样。使用gcmparameterspec
来确定它。
Q5:给定用户知道的持续src数据,我向用户显示无限数量的src数据加密是否安全?
几乎没有束缚,是的。我会在大约2^48次加密后开始担心。然而,一般来说,您应该为密钥更改进行设计。
Q6:如果每次src数据都不一样(例如包括System.CurrentTimeMillis()或随机数),那么我向用户显示无限数量的src数据加密是否安全?
见对问题5的答复
如果我在加密之前用随机数填充src数据会有帮助吗?假设前后各有8个随机字节,还是只在一端?或者这对我的加密没有任何帮助/使我的加密变得更糟?
不,这一点帮助都没有。GCM在下面使用CTR模式,所以它只需要用密钥流加密。它不会起到静脉输液的作用。如果您需要无穷无尽的密文(高于2^48!)那么我建议您使用这个随机数和您的密钥作为密钥派生函数或KDF。HKDF是目前最好的品种,但您可能需要使用弹性城堡或实现自己。
问题内容: 我在Java 8中使用加密,并且想知道我的代码是否存在安全漏洞。我的代码似乎可以 工作 ,因为它可以加密和解密文本,但是一些细节尚不清楚。 我的主要问题是: 该IV是否满足“对于给定的密钥,IV不得重复”的要求。 来自RFC 4106 ? 我也很感激我对相关问题的任何答案/见解(见下文),但第一个问题困扰我最多。我不知道在哪里可以找到答案的源代码或文档。 这是完整的代码,大致。如果写这
我正在考虑使我的应用程序更安全,并了解正在发生的一切。 我在Spring Boot有一个登录名。该登录调用UserDetailsService实现,如下所示: 这为我创建了一个具有用户角色的会话,以便我可以配置网络安全配置器适配器等。 所以我的问题是,用JWT添加过滤器到底做了什么?SpringSecurity在默认情况下是否已经这样做了,因为我所做的已经创建了一个经过授权和身份验证的用户。 谢了
问题内容: 我有一个简单的程序: 当我运行该程序时,我看到的只是用于输出。我原本希望我们会遇到第一轮,然后是,然后是etc。 这是由于这样的事实,一旦我们尝试在左侧重新声明,其值就会重置为? 如果有人可以指出我的详细情况,那将很棒。 更改为,似乎正在按预期方式打印数字。我对它达到最大32位值的速度感到惊讶! 问题答案: 该问题是由于整数溢出引起的。 在32位二进制补码算法中: 确实确实开始具有2的
编写并测试您自己的函数char*funct(char*str,int x),反转字符串str(位置n的字符除外),并返回修改后的str作为结果。函数funct的用途可以是: 这是主要的: 你好CppepC ollH 应该是: 你好Cpp