我AES/GCM/NoPadding
在 Java 8 中使用加密,我想知道我的代码是否存在安全漏洞。我的代码似乎工作,因为它加密和解密文本,但一些细节不清楚。
我的主要问题是:
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 对我来说安全吗?
- 它是否避免了在伽罗瓦/计数器模式中重复使用 IV、组合键的灾难?
- 当我有多个应用程序同时运行此代码时是否仍然安全,所有应用程序都从相同的 src 数据(可能在同一毫秒内)向用户显示加密消息?
- 返回的 IV 是由什么制成的?它是一个原子计数器加上一些随机噪声吗?
- 我是否需要
cipher.getIV()
使用自己的计数器避免并自己构建 IV? cipher.getIV()
假设我使用的是 Oracle JDK 8 + JCE Unlimited Strength 扩展,源代码是否可以在线获得?
那个 IV 总是 12 字节长吗?
身份验证标签是否总是 16 字节(128 位)长?
使用#2 和#3,以及缺少填充,这是否意味着我的加密消息总是
12 + src.length + 16
字节长?(所以我可以安全地将它们压缩成一个字节数组,我知道正确的长度?)给定用户知道的恒定 src 数据,我向用户显示无限数量的 src 数据加密是否安全?
如果每次 src 数据都不同(例如包括
System.currentTimeMillis()
或随机数),我向用户显示无限数量的 src 数据加密是否安全?如果我在加密之前用随机数填充 src 数据会有帮助吗?在前面和后面说 8 个随机字节,还是只在一端?或者这根本没有帮助/让我的加密变得更糟?
(因为这些问题都是关于我自己的代码的同一块,并且它们彼此密切相关,并且其他人在实现相同的功能时可能/应该有相同的问题集,所以将问题分成多个问题感觉不对帖子。如果这更适合 StackOverflow 的格式,我可以单独重新发布它们。让我知道!)