Skip to content

docs: correct the stale SHA1PRNG entropy note - #3481

Merged
pjfanning merged 1 commit into
apache:mainfrom
pjfanning:doc-sha1prng-note
Aug 28, 2026
Merged

docs: correct the stale SHA1PRNG entropy note#3481
pjfanning merged 1 commit into
apache:mainfrom
pjfanning:doc-sha1prng-note

Conversation

@pjfanning

Copy link
Copy Markdown
Member

Motivation

The TLS docs told users that on Linux with SHA1PRNG they should set -Djava.security.egd=file:/dev/urandom "to prevent blocking", and that doing so "is NOT as secure because it reuses the seed". Both halves are wrong on any JDK Pekko supports.

"It reuses the seed" — nothing about /dev/urandom reuses a seed. Since Linux 4.8 both devices draw from the same CSPRNG. The note's instinct is sound but attached to the wrong cause: the real caveat belongs to the algorithm. In sun.security.provider.SecureRandom, SHA1PRNG seeds state once when it is null and then runs a deterministic SHA-1 chain forever, whereas the platform default NativePRNG mixes fresh kernel randomness into every nextBytes call. That holds whatever java.security.egd is set to, so the flag is irrelevant to the concern being raised.

"To prevent blocking" — close to inert. In SeedGenerator, file:/dev/urandom selects NativeSeedGenerator, which on Unix is just URLSeedGenerator reading that path; the special case only means something on Windows. The default securerandom.source is file:/dev/random, which since kernel 5.6 no longer blocks once the pool is seeded at boot. The advice mattered on old kernels in low-entropy VMs.

The same stale rationale is repeated in the reference.conf comments, which justify avoiding SHA1PRNG on the grounds of "blocking issues on Linux".

Modification

Rewrite the note in remote-security.md (artery) and remoting.md (classic) to:

  • lead with the recommendation to keep the platform default SecureRandom;
  • give the no-reseeding property as the reason to prefer it over SHA1PRNG;
  • describe the entropy source accurately, with the blocking concern marked as historical.

Also fixes the missing "to" in the classic copy ("it's recommended specify"), and updates the three reference.conf comments to match.

Result

The note states a caveat that is true and actionable, and no longer advises a JVM flag on grounds that have not applied for several kernel releases.

reference.conf changes are comment-only — no defaults, behaviour, or public API are affected.

Tests

  • Not run - docs only

References

None - follow-up from the threat model review in #3478

Motivation:
The TLS docs told users that on Linux with SHA1PRNG they should set
-Djava.security.egd=file:/dev/urandom "to prevent blocking", and that doing
so "is NOT as secure because it reuses the seed". Both halves are wrong on
any JDK Pekko supports.

Nothing about /dev/urandom reuses a seed: since Linux 4.8 both devices draw
from the same CSPRNG, and since 5.6 /dev/random no longer blocks once the
pool is seeded at boot. The note's instinct is sound but attached to the
wrong cause. The real caveat belongs to the algorithm: in
sun.security.provider.SecureRandom, SHA1PRNG seeds `state` once when it is
null and then runs a deterministic SHA-1 chain forever, whereas the platform
default NativePRNG mixes fresh kernel randomness into every request. That
holds whatever java.security.egd is set to.

The blocking advice is also close to inert. In SeedGenerator, `file:/dev/
urandom` selects NativeSeedGenerator, which on Unix is just URLSeedGenerator
reading that path; the special case only means something on Windows.

The same stale rationale is repeated in the reference.conf comments, which
justify avoiding SHA1PRNG on grounds of "blocking issues on Linux".

Modification:
Rewrite the note in remote-security.md (artery) and remoting.md (classic) to
lead with the recommendation to keep the platform default, give the
no-reseeding property as the reason to avoid SHA1PRNG, and describe the
entropy source accurately with the blocking concern marked as historical.
Fix the missing "to" in the classic copy. Update the three reference.conf
comments to match.

Result:
The note states a caveat that is true and actionable, and no longer advises
a JVM flag on grounds that have not applied for several kernel releases.
Comment-only change to reference.conf; no default or behaviour changes.

Tests:
- Not run - docs only

References:
None - follow-up from threat model review discussion
pjfanning added a commit that referenced this pull request Aug 28, 2026
#3482)

Motivation:
The build and every CI workflow pass -Djava.security.egd=file:/dev/./urandom.
The `/./` is a long-standing workaround whose only effect today is to stop the
string matching SunEntries.URL_DEV_URANDOM:

  DEF_SECURE_RANDOM_ALGO = (NativePRNG.isAvailable() &&
      (seedSource.equals(URL_DEV_URANDOM) || seedSource.equals(URL_DEV_RANDOM))
      ? "NativePRNG" : "DRBG");

So CI resolves `new SecureRandom` to something other than the algorithm users
get. Measured on every JDK in the build matrix:

  JDK   unset        file:/dev/./urandom   file:/dev/urandom
  8     NativePRNG   SHA1PRNG              NativePRNG
  11    NativePRNG   DRBG                  NativePRNG
  17    NativePRNG   DRBG                  NativePRNG
  21    NativePRNG   DRBG                  NativePRNG
  25    NativePRNG   DRBG                  NativePRNG

On the 1.x nightlies that means JDK 8 jobs have been defaulting to SHA1PRNG,
which seeds once at startup and never reseeds. This reaches production code:
SecureRandomFactory maps `random-number-generator = ""` straight to
`new SecureRandom`, so the TLS specs have not been exercising what users run.

The workaround is also no longer needed for its original purpose. On Unix
NativeSeedGenerator extends SeedGenerator.URLSeedGenerator and passes the seed
file through unchanged - verified in the JDK 8 and JDK 21 sources - so
`file:/dev/urandom` reads /dev/urandom and does not block on any supported JDK.
The special case only diverges on Windows.

Modification:
Use `file:/dev/urandom` in PekkoBuild.scala, .jvmopts-ci and the twelve
workflow files. Record why the plain path matters next to the two definitions
that are hand-edited, so the `/./` is not reintroduced.

Result:
CI seeds from a non-blocking source, as before, and `new SecureRandom` resolves
to NativePRNG on every JDK in the matrix, matching an unconfigured JVM. No
change to shipped defaults or to any published artifact.

Tests:
- scalafmt project/PekkoBuild.scala - reformatted, no further changes
- Measured the table above by running `new SecureRandom().getAlgorithm()` under
  each flag on Temurin 8.0.492, 11.0.31, 17.0.19, 21.0.11 and 25.0.3

References:
Refs #3481
@pjfanning
pjfanning merged commit cd5aff2 into apache:main Aug 28, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants