使用OutputStream/InputStream进行加密和HMAC(基于流的先加密后鉴别)

3

我正在寻找一种简单的方法,在Java中使用InputStream / OutputStream计算密文的HMAC(先加密再进行MAC,包括IV和算法参数)。

  • 失败的尝试:我首先尝试从CipherOutputStream继承,但是它们不允许在写入后以编程方式检索密文--这导致我得出结论,只能实现MAC-then-encrypt。代码在此处:http://pastebin.com/armvDN3N

  • 成功的尝试:然后,我使用OpenJDK7源代码中的CipherOutputStream作为基础来实现CipherHmacOutputStream类,每次调用write()时更新Hmac(mac.update()),并在调用close时将其附加到流中。代码在此处:http://pastebin.com/fF8WFBpA

现在的问题是,当我尝试编写匹配的CipherHmacInputStream时,没有明显的方法告诉我何时开始HMAC,因为没有办法告诉流何时结束。available() 方法只返回缓冲区中“新”的解密字节。因此,解密(cipher.update())可能错误地尝试解密HMAC。我已经花了一些时间研究这个问题,但一定有更简单的方法来进行基于流的加密/解密,并使用HMAC。 GCM / EAX是显而易见的答案,但我想让算法/模式可配置,并在不使用GCM / EAX时提供消息身份验证。

你有任何想法吗?是否有任何标准方法可以做到这一点?


关于你第一个“失败”的解决方案。你可以在CipherOutputStreamOutputStream之间添加你的FilterOutputStream来捕获密文。 - Dmitry Zaytsev
1个回答

1
你正在将两个数据块编码成序列化格式。你需要使用某种头部来存储长度,以便稍后隔离每个数据块。同时,在此过程中,添加一个版本号到数据报文中,以便在未来可以保持向后兼容性。

问题在于,虽然具有长度字段的标头非常有用,但是直到最后一个字节被写入之前,密文的长度是未知的。 - binwiederhier
1
HTTP 通过分块处理数据。为每个数据块编写一个字节的标题。如果大小为零,则表示已到达末尾,例如:0xff <255 字节> 0x10 <16 字节> 0x00 <本节结束> - David Ehrmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接