javaaes/GCM/NoPadding-cipher.getIV()给了我什么?
我在Java8中使用了javaaes/GCM/NoPadding-cipher.getIV()给了我什么?,java,security,encryption,cryptography,aes-gcm,Java,Security,Encryption,Cryptography,Aes Gcm,我在Java8中使用了AES/GCM/NoPadding加密,我想知道我的代码是否存在安全漏洞。我的代码似乎可以工作,因为它可以对文本进行加密和解密,但一些细节还不清楚 我的主要问题是: Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] iv = cipher.getIV(); // ????? 该IV是否满足“对于给定的密钥,IV不得重复
AES/GCM/NoPadding
加密,我想知道我的代码是否存在安全漏洞。我的代码似乎可以工作,因为它可以对文本进行加密和解密,但一些细节还不清楚
我的主要问题是:
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = cipher.getIV(); // ?????
该IV是否满足“对于给定的密钥,IV不得重复”的要求 我也很感谢您对我的相关问题的回答/见解(见下文),但第一个问题最让我困扰。我不知道在哪里可以找到回答这个问题的源代码或文档
下面是完整的代码,大致如下。如果在撰写本文时出现错误,我深表歉意:
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);
}
}
类加密机{
钥匙;
加密程序(字节[]密钥){
如果(key.length!=32)抛出新的IllegalArgumentException();
this.key=新的SecretKeySpec(key,“AES”);
}
//输出将发送给用户
字节[]加密(字节[]src)引发异常{
Cipher Cipher=Cipher.getInstance(“AES/GCM/NoPadding”);
cipher.init(cipher.ENCRYPT_模式,密钥);
byte[]iv=cipher.getIV();//参见问题1
assert iv.length==12;//参见问题2
字节[]密文=cipher.doFinal(src);
assert cipherText.length==src.length+16;//参见问题3
字节[]消息=新字节[12+src.length+16];//参见问题4
系统阵列复制(iv,0,消息,0,12);
System.arraycopy(密文,0,消息,12,密文长度);
返回消息;
}
//输入来自用户
字节[]解密(字节[]消息)引发异常{
if(message.length<12+16)抛出新的IllegalArgumentException();
Cipher Cipher=Cipher.getInstance(“AES/GCM/NoPadding”);
GCMParameterSpec params=新的GCMParameterSpec(128,消息,0,12);
cipher.init(cipher.DECRYPT_模式,密钥,参数);
返回cipher.doFinal(message,12,message.length-12);
}
}
假设用户破解我的密钥=游戏结束
更详细的问题/相关问题:
- 它是否避免了在Galois/Counter模式下重用IV键组合的灾难
- 当我有多个应用程序同时运行此代码,所有应用程序都从相同的src数据(可能在相同的毫秒内)向用户显示加密消息时,它仍然安全吗
- 退回的IV是什么做的?是原子计数器加上一些随机噪声吗
- 我是否需要避免使用cipher.getIV()并使用自己的计数器构造一个IV
- 假设我使用的是OracleJDK8+JCE无限强度扩展,那么实现
的源代码是否在线提供cipher.getIV()
12+src.length+16
字节长?(这样我就可以安全地将它们压缩成一个字节数组,我知道正确的长度?)System.currentTimeMillis()
或随机数),我向用户显示无限数量的src数据加密是否安全(因为这些问题都是关于我自己代码的同一块,并且它们彼此之间有着密切的关系,其他人在实现相同功能时可能/应该有相同的问题集,所以将这些问题拆分为多个帖子是错误的。如果这更适合StackOverflow的话,我可以分别重新发布它们。)格式化。让我知道!)Q1:cipher.getIV()返回的IV对我这样使用安全吗? 是的,它至少适用于Oracle提供的实现。它是使用默认的
SecureRandom
实现单独生成的。由于它的大小为12字节(GCM的默认值),因此有96位随机性。计数器重复的可能性非常小。您可以在OpenJDK(GPL'ed)中查找源代码oraclejdk是基于它的
但是,我仍然建议您生成自己的12个随机字节,因为其他提供者的行为可能不同
Q2:IV总是12字节长吗? 这是极有可能的,因为它是GCM默认值,但其他长度对GCM有效。不过,该算法必须对12字节以外的任何其他大小进行额外计算。由于存在缺陷,强烈建议将其保持在12字节/96位,API可能会限制您选择IV大小
Q3:身份验证标签是否总是16字节(128位)长? 不,它可以有64位到128位的字节大小,增量为8位。如果它较小,则只包含身份验证标记最左边的字节。您可以使用另一个标记大小作为
init
调用的第三个参数
请注意,GCM的强度很大程度上取决于标记的大小。我建议将其保持在128位。96位应该是最小值,尤其是如果您想生成大量密文
Q4:有了#2和#3,并且没有填充,这是否意味着我的加密消息总是12+src.length+16字节长?(这样我就可以安全地将它们压缩到一个字节数组中,我知道正确的长度了? 请参见上文。对于Oracle提供程序,情况就是这样。请使用