Definition and Overview

A Cryptographically Secure Pseudo-Random Number Generator (CSPRNG) is an algorithm that produces sequences of numbers that are computationally indistinguishable from truly random sequences. Unlike standard pseudo-random number generators (PRNGs) used for simulations or games, CSPRNGs must satisfy stringent security requirements: an adversary who knows the algorithm and has observed arbitrarily many output bits cannot predict the next bit with probability significantly better than 50%.

The distinction between a PRNG and a CSPRNG is critical in security-sensitive applications. A standard PRNG like Mersenne Twister produces statistically well-distributed numbers but is entirely deterministic -- observing 624 consecutive 32-bit outputs allows full state recovery and prediction of all future outputs. A CSPRNG, by contrast, maintains security even against adversaries with substantial computational resources. This property is essential for generating cryptographic keys, session tokens, nonces, and any value whose unpredictability is a security requirement.

Modern CSPRNGs draw initial entropy from hardware sources (CPU thermal noise, interrupt timing jitter, mouse movements) and use cryptographic primitives (block ciphers, hash functions) to stretch this entropy into arbitrary-length output streams. The BEAM virtual machine delegates to OpenSSL's CSPRNG implementation through the :crypto module, providing Elixir and Erlang applications with access to operating system entropy pools without requiring custom implementation.

Technical Deep Dive

CSPRNGs must satisfy three formal security properties that distinguish them from ordinary PRNGs:

PropertyDefinitionConsequence of Violation
Next-bit unpredictabilityGiven k output bits, no polynomial-time algorithm can predict bit k+1 with probability > 1/2 + negligibleAttacker can predict tokens, keys, nonces
Backtracking resistanceCompromised internal state does not reveal previously generated outputsPast sessions compromised by current state leak
Prediction resistanceCompromised internal state does not allow prediction of future outputs after re-seedingForward secrecy violated even after state recovery

Common CSPRNG Constructions

ConstructionBasisUsed ByPerformance
CTR_DRBGAES in counter modeNIST SP 800-90A, OpenSSLFast, hardware-accelerated
HASH_DRBGSHA-256/SHA-512NIST SP 800-90AModerate, widely available
HMAC_DRBGHMAC-SHA-256NIST SP 800-90A, JavaModerate, proven security
ChaCha20ChaCha20 stream cipherLinux /dev/urandom, arc4randomVery fast, cache-timing resistant
FortunaAES-256 + SHA-256FreeBSD, macOSRobust entropy management

Entropy Sources

The security of any CSPRNG ultimately depends on the quality of its entropy source. Modern systems combine multiple sources:

Hardware Sources:
  - CPU RDRAND/RDSEED instructions (Intel, AMD)
  - Thermal noise from hardware components
  - Interrupt timing jitter (keyboard, disk, network)
  - Platform-specific (TPM, HSM)

Software Sources:
  - Process scheduling timing
  - Memory allocation patterns
  - Network packet arrival times
  - User input timing (mouse, keyboard)

Architecture and Implementation

The architecture of a CSPRNG consists of three core components: an entropy accumulator that collects randomness from hardware and software sources, a seed manager that maintains and periodically refreshes the internal state, and an output generator that produces the actual random byte sequences.

The entropy accumulator continuously gathers environmental noise and estimates the accumulated entropy in bits. When sufficient entropy has been collected (typically 256 bits for modern security levels), the seed manager mixes it into the generator's internal state through a cryptographic mixing function. The output generator then uses this state to produce random bytes on demand, typically through a block cipher in counter mode or a hash-based construction.

Re-seeding is a critical operation that prevents catastrophic failure if the internal state is ever compromised. By periodically mixing fresh entropy into the state, a CSPRNG ensures that even a state compromise is transient -- after the next re-seed, the generator's output is once again unpredictable to an adversary who knew the previous state.

Usage in Prismatic Platform

The Prismatic Platform relies on CSPRNGs for all security-critical random value generation, from API tokens and session identifiers to cryptographic nonces and salts. Elixir's :crypto.strong_rand_bytes/1 function provides the primary interface to the system CSPRNG.

defmodule Prismatic.Security.TokenGenerator do
  @moduledoc """
  Generates cryptographically secure tokens using BEAM's
  :crypto module, which delegates to OpenSSL's CSPRNG.

  All tokens in the platform use this module to ensure
  unpredictability and resistance to brute-force attacks.
  """

  @token_byte_length 32
  @api_key_byte_length 48
  @nonce_byte_length 16

  @spec generate_session_token() :: String.t()
  def generate_session_token do
    @token_byte_length
    |> :crypto.strong_rand_bytes()
    |> Base.url_encode64(padding: false)
  end

  @spec generate_api_key() :: String.t()
  def generate_api_key do
    prefix = "prism_"
    random_part =
      @api_key_byte_length
      |> :crypto.strong_rand_bytes()
      |> Base.url_encode64(padding: false)

    prefix <> random_part
  end

  @spec generate_nonce() :: binary()
  def generate_nonce do
    :crypto.strong_rand_bytes(@nonce_byte_length)
  end

  @spec generate_csrf_token() :: String.t()
  def generate_csrf_token do
    :crypto.strong_rand_bytes(24)
    |> Base.url_encode64(padding: false)
  end

  @doc """
  Generates a time-limited token by combining CSPRNG output
  with a timestamp and HMAC signature.
  """
  @spec generate_timed_token(String.t(), pos_integer()) :: String.t()
  def generate_timed_token(secret_key, ttl_seconds) do
    nonce = :crypto.strong_rand_bytes(@nonce_byte_length)
    expires_at = System.system_time(:second) + ttl_seconds
    payload = <<expires_at::64, nonce::binary>>

    signature =
      :crypto.mac(:hmac, :sha256, secret_key, payload)
      |> binary_part(0, 16)

    Base.url_encode64(payload <> signature, padding: false)
  end
end

Security Considerations in BEAM

ConcernBEAM BehaviorMitigation
Process isolationEach process has independent memoryCSPRNG state not shared between processes
Hot code upgradeModule reload during runtime:crypto state persists through upgrades
DistributionErlang distribution protocolTokens generated locally, not transmitted via distribution
Memory inspectionProcess heap readable via :erlang.process_info/2Generate tokens immediately before use, do not store in process state

The platform enforces CSPRNG usage through Credo checks that flag usage of :rand.uniform/1 or Enum.random/1 in security-sensitive modules. The forbidden patterns enforcement system blocks any use of weak randomness in authentication, session management, or cryptographic code paths.

Cross-References

  • HMAC Signature -- Message authentication using keyed hashes
  • CSRF -- Cross-site request forgery prevention requires CSPRNG tokens
  • AES -- Block cipher used in CTR_DRBG construction
  • Session Management -- Session tokens require cryptographic randomness
  • Livebooks: security_compliance/ notebooks demonstrate token generation and analysis
  • Academy: APISecurityAnalysis topic covers secure token practices

Connect & Contribute

Created by Tomas Korcak (korczis) | Open Source under GHL