在Java中,Mac#doFinal()是线程安全的吗?

19

在Java中,我们需要为太多的文本数据生成HmacSHA1/256消息摘要,当然需要进行并行处理。

现在的问题是,javax.crypto.Mac#doFinal(byte[]:arg)线程安全吗?或者说在sun/oracle(hotspot)的实现SPI中是否更好?

所有的盐密钥都是相同的,我考虑准备一个Mac对象,并让所有线程调用它来生成消息摘要。

我无法理解并在javadoc中描述它。

如果这个方法不是线程安全的,是否有任何类似的替代方法(也许来自Apache等)?

谢谢。


1
鉴于Mac是一个有状态的对象,我怀疑它不能被多个线程用于生成几个不同的摘要。为什么不在每次需要计算摘要时创建一个实例?您已经证明这会导致显着的性能损失,特别是与摘要本身涉及的复杂加密计算相比吗?这听起来像是过早优化。最好的方法是将Mac实例存储在ThreadLocal中,以便每个线程都有一个实例。 - JB Nizet
@JBNizet 我们可能需要在一秒钟内生成超过10个摘要,我知道生成哈希的过程,并且目前我为每个线程生成一个并保留。我只是想知道是否可以有一个全局变量,所有线程都使用它,我认为Mac会在每个请求中复制所需的信息(数据、密钥)并生成它,这样它就是线程安全的(而静态方法则不是)。希望它有点像轮询,每个线程都有一个。谢谢 - user5207035
1个回答

22

javax.crypto.Mac#doFinal 方法都不是线程安全的,因为它们会改变 MAC 的内部状态。

这是有道理的,因为在任何时候,MAC 都类似于到那个时间点所有先前 MAC 的总和/异或运算,所以它不能并行完成。就我所知,没有一种 MAC 算法可以并行工作(与某些加密算法相反)。

尽管如此,Mac 是可克隆的,所以如果您拥有已计算盐的实例,您可以克隆它并使用克隆来计算 MAC(但我建议测试一下!)


此外,似乎Mac对象甚至不是“串行”线程安全的。 - Stephen C
@StephenC 这是因为它并不是。HMAC实例化不应该太重。仅为每个文本生成一个HMAC要好得多。 - Maarten Bodewes
Augusto:你可以从哈希树(或 Merkle 树)创建一个哈希函数。但通常的哈希算法纯粹是顺序的。 - Maarten Bodewes
我的意思是...我已经查看了源代码,看起来Mac对象和底层SPI对象甚至都不是串行线程安全的。 - Stephen C

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