Kim Hage created LANG-1748:
------------------------------
Summary: RandomStringUtils.random() drains the systems entropy
pool and blocks
Key: LANG-1748
URL: https://issues.apache.org/jira/browse/LANG-1748
Project: Commons Lang
Issue Type: Bug
Affects Versions: 3.15.0
Environment: {{*java -version*
openjdk version "17.0.9" 2023-10-17
OpenJDK Runtime Environment Temurin-17.0.9+9 (build 17.0.9+9)
OpenJDK 64-Bit Server VM Temurin-17.0.9+9 (build 17.0.9+9, mixed mode, sharing)
*/proc/version*
Linux version 3.10.0-1160.119.1.el7.x86_64 ([email protected])
(gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) ) #1 SMP Tue Jun 4
14:43:51 UTC 2024
*/etc/centos-release*
CentOS Linux release 7.9.2009 (Core)
*/sys/devices/virtual/misc/hw_random/rng_available* is empty
}}
Reporter: Kim Hage
Since we upgraded to Version 3.15 of commons-lang we have experienced
performance problems and timeout issues during deployments. Our analysis
suggests that this is due to issues introduced with [this
change|https://github.com/apache/commons-lang/pull/1250], namely the use of
{{{}SecureRandom.{}}}{{{}getInstanceStrong(){}}} in
{{{}src/main/java/org/apache/commons/lang3/RandomUtils.java{}}}.
SecureRandom.getInstanceStrong() uses /{{{}dev/random{}}} instead of
{{/dev/urandom}} on linux systems. which leads to terrible performance when
little entropy is available on the system.
Here is what seems to happen in our case
* Our deployments use Liquibase for database schema migrations
* [Liquibase uses RandomStringUtils to generate internal
identifiers|https://github.com/liquibase/liquibase/blob/e854a6e18c29651da0d51265a28c58f22ef3248b/liquibase-standard/src/main/java/liquibase/Scope.java#L154],
and it generates quite a few of them. (This might be a strange decision on
their side as well, but probably not the issue here)
* Each call to RandomStringUtils.random() takes a few bytes out of the systems
entropy pool. This can be traced by calling {{{}cat
/proc/sys/kernel/random/entropy_avai{}}}l on the linux shell.
* The systems entropy pool gets drained quickly and when it is empty, calls to
RandomStringUtils.random() will block until new entropy becomes available.
Since we are running on a virtual machine, new bytes are added very slowly to
the systems entropy pool (about 3-4 bytes per second)
* Ultimately, our deployments fail with a timeout because Liquibase was unable
to finish in time
I am not a security expert, but the general consensus on the internet seems to
be that using /dev/urandom instead of /dev/random should be equally secure for
almost all use cases.
Maybe the call to {{SecureRandom.getInstaceStrong()}} in {{RandomUtils}} could
be replaced with {{{}new SecureRandom(){}}}. Calls to
RandomStringUtils.random(...) should then be no longer blocking (probably).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)