在 JAVA 中使用 AES/GCM 检测不正确的密钥
Posted
技术标签:
【中文标题】在 JAVA 中使用 AES/GCM 检测不正确的密钥【英文标题】:Detecting incorrect key using AES/GCM in JAVA 【发布时间】:2012-08-27 00:48:03 【问题描述】:我正在使用 AES
使用 BouncyCastle 在 GCM
模式下加密/解密一些文件。
虽然我证明了错误的解密密钥,但也不例外。
我应该如何检查密钥是否不正确?
我的代码是这样的:
SecretKeySpec incorrectKey = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] block = new byte[1048576];
int i;
cipher.init(Cipher.DECRYPT_MODE, incorrectKey, ivSpec);
BufferedInputStream fis=new BufferedInputStream(new ProgressMonitorInputStream(null,"Decrypting ...",new FileInputStream("file.enc")));
BufferedOutputStream ro=new BufferedOutputStream(new FileOutputStream("file_org"));
CipherOutputStream dcOut = new CipherOutputStream(ro, cipher);
while ((i = fis.read(block)) != -1)
dcOut.write(block, 0, i);
dcOut.close();
fis.close();
谢谢
【问题讨论】:
如果您能接受更多答案并跟进您的问题 4r1y4n(我想那将是 Ariyan),那就太好了 您不接受加密问题 4r1y4n 的答案是否有特定原因,或者它们只是逃避了您的注意?您没有连续接受任何 4 个。 请注意:Java 7 中的 AEAD 模式与 CipherInputStream 组合不受完整性保护:github.com/binwiederhier/syncany/issues/… 对我来说,CipherInputStream 在 Java 8u25 中工作。我在 Oracle 的发行说明中找不到他们对 CipherInputStream 进行了更新。 【参考方案1】:没有任何方法可以在 GCM 模式下检测到不正确的键。您可以检查的是身份验证标签是否有效,这意味着您使用了正确的密钥。问题是,如果身份验证标签不正确,那么这可能表明以下各项(或所有内容的组合,直至并包括完全替换密文和身份验证标签):
-
使用了不正确的密钥;
计数器模式加密数据在传输过程中被更改;
其他经过身份验证的数据已更改;
身份验证标签本身在传输过程中被更改。
您可以做的是发送额外的数据来识别所使用的密钥。这可能是一个可读的标识符 ("encryption-key-1"
),但它也可能是一个 KCV,一个密钥检查值。 KCV 通常由使用密钥加密的零块或密钥上的加密安全哈希(也称为指纹)组成。因为零块上的加密会泄漏信息,所以您不应该使用它来识别加密密钥。
您实际上可以使用 GCM 模式的 AAD 功能来计算密钥标识数据上的身份验证标签。请注意,您无法区分指纹泄露和使用不正确的密钥。但是指纹被意外损坏的可能性比IV、AAD、密文和认证标签的整个结构要小。
【讨论】:
【参考方案2】:您正在使用NoPadding
。将其更改为 PKCS7Padding
以进行加密和解密。如果使用了错误的密钥,那么填充几乎肯定无法按预期解密,并且会抛出 InvalidCipherTextException
。
【讨论】:
1) GCM 是一种流模式,因此不需要填充 2) 依靠填充进行完整性检查是一个非常糟糕的主意。您很可能会以这种方式向填充预言家敞开心扉。 3) GCM 有一个集成的 MAC,它已经处理了您需要的任何完整性检查。 问题是关于识别不正确的密钥,而不是完整性检查。对于该特定问题,使用填充很好。你对 GCM 的看法是正确的,我的错。 非常罕见的失传玫瑰,我相信我会赚更多。你介意我把它放在我的罕见失误收藏中吗? :)以上是关于在 JAVA 中使用 AES/GCM 检测不正确的密钥的主要内容,如果未能解决你的问题,请参考以下文章
Java AES/GCM/NoPadding 加密在 doFinal 之后不会增加 IV 的计数器
使用 Java 8u20 进行慢速 AES GCM 加密和解密