Safeguard
Application Security•

Secure random numbers and cryptography basics in Scala

Use java.security.SecureRandom for tokens and keys in Scala, never a seeded generator, and let a maintained library handle AES modes, IVs and key storage.

Safeguard Security Team
4 min read

In Scala, generate tokens, session IDs and keys with java.security.SecureRandom, never with a seeded or general purpose generator. Use AES through a maintained library with an authenticated mode, let the library choose nonces, and keep keys out of source code.

Why does the kind of random number matter?

Scala runs on the JVM, so it uses the Java security classes. The JDK documentation says SecureRandom provides a cryptographically strong random number generator. Such a generator minimally complies with the statistical tests in section 4.9.1 of FIPS 140-2, and it must produce non deterministic output. The documentation also says any seed material passed to a SecureRandom must be unpredictable, and that its output must be cryptographically strong as described in RFC 4086.

A general purpose generator is built for speed and repeatability. If an attacker sees enough outputs, or knows the seed, they can predict the next values. For a coupon shuffle that does not matter. For a password reset token it decides whether accounts can be taken over.

A constructed bug: a service creates reset tokens from a generator seeded with the current time in milliseconds. An attacker who requests a token for their own account knows the time window and can try a few thousand candidates for the victim's.

How do you get a SecureRandom?

The JDK docs show three ways: the no argument constructor, getInstance with an algorithm name, and getInstance with a DRBG algorithm and parameters such as security strength. There is also getInstanceStrong, which uses the algorithms and providers set in the securerandom.strongAlgorithms security property.

In practice a single shared instance created with the default constructor is the right default for most services. Do not call setSeed with predictable input. Reach for getInstanceStrong only when your policy asks for the providers named in that property.

NIST SP 800-90A Rev. 1 describes deterministic random bit generators, the construction behind DRBG algorithms. Read it if you need to know why the design is considered sound.

Which algorithms should you use?

The OWASP Cryptographic Storage Cheat Sheet recommends AES for symmetric encryption with a key of at least 128 bits, ideally 256, in a secure mode, and says authenticated modes should always be used where available because they guarantee integrity and authenticity as well as confidentiality. For public key work it recommends a maintained library implementing an established hybrid scheme, and it discusses ML-KEM from NIST FIPS 203 for post quantum migration planning.

The cheat sheet also notes that some modes need secure initialization vectors, and that these should be handled automatically by the library. If you are choosing an IV by hand in a Cipher call, take that as a sign to use a higher level library.

What about keys and storage?

The same cheat sheet says to minimise storage of sensitive information in the first place, and it points to secrets management systems, noting they add complexity but make management easier. Load keys from a secrets manager or environment at start up, not from a constant in a Scala object, and do not log them.

How to check or apply this

  1. Search the codebase for scala.util.Random and java.util.Random used in security contexts such as tokens, passwords, salts and keys.
  2. Replace them with a shared SecureRandom instance.
  3. Delete any setSeed calls with predictable values.
  4. Use AES with an authenticated mode through a maintained library, and check that the library generates nonces.
  5. Move keys into a secrets manager and rotate any that ever lived in source.
  6. Add a static analysis rule that flags non cryptographic generators in security packages.
  7. Track the cryptography libraries in your dependency inventory, so a vulnerability in one is found fast.

Quick check

Is SecureRandom slower than other generators?

Usually somewhat, and that is the price of unpredictability. For tokens and keys the cost is rarely noticeable.

Can I seed SecureRandom for reproducible tests?

Avoid it in production code. The JDK says seed material must be unpredictable, so a fixed seed defeats the purpose. Tests that need repeatable values should use a separate test generator.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.