web-dev-qa-db-ja.com

暗号はスレッドセーフですか?

簡単に言えば、_javax.crypto.Cipher_の1つのインスタンス(たとえばCipher.getInstance("RSA"))を複数のスレッドから使​​用できますか、またはそれらの複数をThreadLocalに固定する必要がありますか(私の場合)。 ?

58

いいえ、そうではありません。インスタンスはステートフルです。したがって、それをスレッドローカルに保存するか、すべての暗号化/復号化呼び出しで新しいインスタンスを取得するか、synchronized(cipher)ブロックでラップする必要があります。

スレッドセーフは通常、javadocで言及されている explicitly です。これは Cipher の場合ではないため、スレッドセーフであると想定しないでください。

90
BalusC

Cipherがスレッドセーフであったとしても、複数のスレッドから同時にそれを使用することは実際には役に立ちません。

updateおよびfinishメソッドを介して)Cipherに出し入れするバイトは、連続したストリームです。つまり、反対側では、意味をなすために同じ順序で渡す必要があります。これを行うスレッドが1つしかない場合、これは最も簡単に実行できます。

複数のスレッドを使用している場合は、通常、呼び出しの間にresetを呼び出す必要があります-とにかく外部同期が必要になります。

7
Paŭlo Ebermann

同期せずに複数のスレッドのCipherオブジェクトを使用しません。 APIを見ると、init()update()など、内部状態を変更することによってのみ機能するメソッドがあります。これにより、暗黙的にスレッドセーフではなくなります。

7
ddso

暗号はスレッドセーフではありません。

パフォーマンスのためにマルチスレッドを使用し、同期を行いたくない場合は、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にアクセスするために内部で同期を行います。

2
Anton Yuriev