Cipher线程安全吗?

Bar*_*lom 58 java encryption multithreading thread-safety

很简单,可以从多个线程中使用javax.crypto.Cipher(例如Cipher.getInstance("RSA"))一个实例,还是需要在ThreadLocal(在我的情况下)将多个实例中的多个实例中使用?

Bal*_*usC 95

不,不是.该实例是有状态的.因此,您需要将其存储为threadlocal,或者在每个加密/解密调用上获取新实例,或者将其包装在synchronized(cipher)块中.

线程安全通常在javadoc中明确提到.情况并非如此Cipher,因此您不应该认为它是线程安全的.

  • 许多Javadoc明确表示"不是线程安全的":[Google](https://www.google.co.uk/search?source=ig&hl=en&rlz=&q=%22is+not+thread+safe%22+site% 3Ahttp%3A%2F%2Fdocs.oracle.com%2Fjavase%2F6%2Fdocs%2Fapi%2F&btnG =谷歌搜索+&元= LR%3D&水溶液= F&AQI = G10&AQL =&OQ =&gs_rfai =) (3认同)

Paŭ*_*ann 8

即使Cipher是线程安全的,同时从多个线程使用它也没有用.

您放入和离开Cipher的字节(通过它updatefinish方法)是一个连续的流.这意味着,另一方面,它们必须以相同的顺序传递才有意义.如果您只有一个线程执行此操作,这是最容易实现的.

如果您使用多个线程,通常需要在两次调用reset之间进行调用 - 然后无论如何都需要外部同步.


dds*_*dso 7

我不会在没有同步的情况下使用来自多个线程的Cipher对象.当您查看API时,有些方法只能通过更改内部状态来工作,例如init()update().这使得它们隐含地非线程安全.


Ant*_*iev 6

密码不是线程安全的。

如果您使用多线程来提高性能并且不想进行同步,您可以使用 Jasypt ( http://www.jasypt.org/general-usage.html ),它具有池化加密器:PooledPBEByteEncryptor、PooledPBEStringEncryptor。

如果同步适合您并且您使用 Spring。您可以使用加密器(https://docs.spring.io/spring-security/site/docs/4.2.5.RELEASE/apidocs/org/springframework/security/crypto/encrypt/Encryptors.html)。他们在内部进行同步以访问 Cipher。