Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javaaes/GCM/NoPadding-cipher.getIV()给了我什么?_Java_Security_Encryption_Cryptography_Aes Gcm - Fatal编程技术网

javaaes/GCM/NoPadding-cipher.getIV()给了我什么?

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不得重复

我在Java8中使用了
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);
}
}
假设用户破解我的密钥=游戏结束


更详细的问题/相关问题:

  • cipher.getIV()返回的IV以这种方式使用安全吗

    • 它是否避免了在Galois/Counter模式下重用IV键组合的灾难
    • 当我有多个应用程序同时运行此代码,所有应用程序都从相同的src数据(可能在相同的毫秒内)向用户显示加密消息时,它仍然安全吗
    • 退回的IV是什么做的?是原子计数器加上一些随机噪声吗
    • 我是否需要避免使用cipher.getIV()并使用自己的计数器构造一个IV
    • 假设我使用的是OracleJDK8+JCE无限强度扩展,那么实现
      cipher.getIV()
      的源代码是否在线提供
  • IV总是12字节长吗

  • 身份验证标记是否总是16字节(128位)长

  • 有了#2和#3,并且没有填充,这是否意味着我的加密消息总是
    12+src.length+16
    字节长?(这样我就可以安全地将它们压缩成一个字节数组,我知道正确的长度?)

  • 给定用户知道的恒定src数据,向用户显示无限数量的src数据加密是否安全

  • 如果src数据每次都不同(例如,包括
    System.currentTimeMillis()
    或随机数),我向用户显示无限数量的src数据加密是否安全

  • 如果我在加密前用随机数填充src数据会有帮助吗?前面和后面是8个随机字节,还是只在一端?或者这根本没有帮助/让我的加密更糟糕


  • (因为这些问题都是关于我自己代码的同一块,并且它们彼此之间有着密切的关系,其他人在实现相同功能时可能/应该有相同的问题集,所以将这些问题拆分为多个帖子是错误的。如果这更适合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提供程序,情况就是这样。请使用