Reading through the forum it seems the SecureRandom
is thread safe, but it struggles in multi-threaded systems because of contention see Is SecureRandom thread safe?
. Also initialising a new SecureRandom
is an expensive operation. One suggestion to improve the performance is to use ThreadLocalRandom.
So I changed my code from:
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
to:
private final ThreadLocalRandom randomThreadLocal = ThreadLocalRandom.current();
I did some tests - 100 runs for encrypting 10000 string values and I can see definite improvement.
**With ThreadLocalRandom**
Thread #18New encryption service took on average: 66.44ms.
Thread #17New encryption service took on average: 64.79ms.
Thread #14New encryption service took on average: 70.77ms.
Thread #13New encryption service took on average: 72.33ms.
Thread #19New encryption service took on average: 73.42ms.
Thread #15New encryption service took on average: 74.21ms.
Thread #11New encryption service took on average: 76.79ms.
Thread #16New encryption service took on average: 78.72ms.
Thread #12New encryption service took on average: 78.95ms.
Thread #20New encryption service took on average: 78.99ms.
**With SecureRandom**
Thread #19New encryption service took on average: 87.26ms.
Thread #18New encryption service took on average: 93.65ms.
Thread #13New encryption service took on average: 93.1ms.
Thread #15New encryption service took on average: 95.81ms.
Thread #16New encryption service took on average: 96.9ms.
Thread #11New encryption service took on average: 97.0ms.
Thread #20New encryption service took on average: 94.93ms.
Thread #17New encryption service took on average: 96.63ms.
Thread #12New encryption service took on average: 97.41ms.
Thread #14New encryption service took on average: 99.08ms.
It seems I definitely improved the speed here, however I degraded the security because it seems the ThreadLocalRandom is not cryptographically secure:
* <p>Instances of {@code ThreadLocalRandom} are not cryptographically
* secure. Consider instead using {@link java.security.SecureRandom}
* in security-sensitive applications
My question is - is there a way to create cryptographically secure Random number, which is thread safe and it's performing well in a multi-threaded system?
There is one more question touching this topic, however the answer is suggesting the same transition from SecureRandom
-> ThreadLocalRandom
, which is not cryptographically secure see Minimizing SecureRandom performance problems in multithreaded environment?.