java - 使用 AES/CTR 模拟流密码

标签 java encryption cryptography aes bouncycastle

我正在编写一个应用程序服务器,我决定使用 AES128/CTR/NoPadding 来保护连接,因为它被认为足够安全而不必将字节扩展到 block 边界,我认为它非常适合到逻辑上是无缝流的 TCP。

问题是 Cipher.update() 在它有一个完整的 16 字节 block 之前不会返回加密 block ,因为 CTR 基本上是基于 block 密码虽然模拟流密码。我应该从 tcp 套接字读取数据并在消息到达时立即处理消息,但我无法检索最新的 block ,因为它仍在构建并且其大小小于 16 字节。我等不及了,因为我们不知道下一条消息何时发送。当然,我可以调用 Cipher.doFinal() 来获取剩余部分,但这意味着流(连接)结束并且 Cipher 对象将被重新初始化。

我认为如果有一种方法可以查看结转,那就太好了。 CTR 只是将纯文本与 key 流进行异或运算,因此无论 block 中的其余字节如何,我都应该能够获得加密数据。这个问题会有很好的解决方法吗?我正在考虑编写一个包装器,用零加密伪造的纯文本以提前获取 key 流并手动进行 XOR,但我想知道其他人是如何解决这个问题的。

更新

我正在开发一个 Android 应用程序,结果发现这是 Dalvik VM 的问题。正如 Robert 和 monnand 在下面指出的那样,Java SE 至少在默认提供程序中没有这个问题。我想我必须编写一个包装类或将模式更改为 CFB8 才能解决这个问题。 (CTR8 不工作)感谢所有回复!

最佳答案

我刚刚使用 Oracle Java 1.7 在 CTR 模式下测试了 AES,我无法验证您的观察结果:

Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
KeyGenerator kg = KeyGenerator.getInstance("AES");
c.init(Cipher.ENCRYPT_MODE, kg.generateKey());
System.out.println(c.update(new byte[1]).length);  // output: 1
System.out.println(c.update(new byte[20]).length); // output: 20

可能是您使用了有缺陷的第三方实现,因为“AES128/CTR/NoPadding”在我的系统上不是已知密码。

关于java - 使用 AES/CTR 模拟流密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16292694/

相关文章:

php - 在 Objective C 中签名字符串并在 PHP 中验证 - 不工作

java - 启动后,Android应用程序崩溃。按钮问题?

java - 在 Java 中使用 HashMap 创建表

java - 从 Java 或 C# 访问一个用 Python 编写的返回数组的函数

javascript - 我的 Node 中的 PBKDF2 有什么问题吗?

cryptography - 从 DER 解码字符串创建 X509Certicate

java - Android 上的 JNI,如何将 int 从 c 传递到 java

jquery - 有没有办法在 jQuery 中加密?

encryption - 在 ssl 之上的应用层加密数据

c# - C# 和 PHP 中的 TripleDES 加密结果不一样(PKCS7、ECB)?