phalcon/cphalcon · error · RandomBytesGenerationFailed

Cannot calculate Random Pseudo Bytes

Error message

Cannot calculate Random Pseudo Bytes

What it means

Crypt::encrypt() obtains its IV by calling openssl_random_pseudo_bytes($ivLength) inside a try block; any Throwable escaping that call is swallowed and rethrown as RandomBytesGenerationFailed. This is an environment-level failure of the OS/openssl CSPRNG, not a problem with your data or key.

Source

Thrown at phalcon/Encryption/Crypt.zep:351

            let encryptKey = key;
        }

        if true === empty(encryptKey) {
            throw new EmptyEncryptionKey();
        }

        let cipher   = this->cipher,
            ivLength = this->ivLength;

        this->checkCipherHashIsAvailable(cipher, "cipher");

        let mode      = this->getMode(),
            blockSize = this->getBlockSize(mode);

        try {
            let iv = this->phpOpensslRandomPseudoBytes(ivLength);
        } catch \Throwable {
            throw new RandomBytesGenerationFailed();
        }

        let padded = this->encryptGetPadded(mode, input, blockSize);

        /**
         * If the mode is "gcm" or "ccm" and auth data has been passed call it
         * with that data
         */
        let encrypted = this->encryptGcmCcm(mode, padded, encryptKey, iv);

        if true === this->useSigning {
            let digest = this->phpHashHmac(
                this->getHashAlgorithm(),
                padded,
                encryptKey,
                true
            );

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Verify the CSPRNG works in that exact environment: php -r 'var_dump(bin2hex(random_bytes(16)));' and the same for openssl_random_pseudo_bytes(16).
  2. If the container restricts devices, ensure /dev/urandom is available/mounted (check docker run device rules, seccomp profiles).
  3. Reinstall/align the php-openssl and libssl packages (same repository/version series) - a mismatched build is the usual culprit.
  4. As a code-level workaround you cannot inject the IV into Crypt, so fixing the runtime is the only real option; validate environment in a health check.

Example fix

// before (env is broken, no code fix applies)
$token = $crypt->encrypt($payload); // RandomBytesGenerationFailed

// after: add a boot diagnostic so the real fault is visible
$ivOk = @openssl_random_pseudo_bytes(16);
if ($ivOk === false) {
    throw new \RuntimeException('openssl CSPRNG unavailable - check /dev/urandom and php-openssl');
}
$token = $crypt->encrypt($payload);
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe the CSPRNG in the target environment before relying on Crypt:
if (false === @openssl_random_pseudo_bytes(16)) {
    throw new \RuntimeException('openssl CSPRNG unavailable - fix runtime (check /dev/urandom, php-openssl)');
}

Try / catch

try {
    $token = $crypt->encrypt($payload);
} catch (\Phalcon\Encryption\Crypt\Exception\RandomBytesGenerationFailed $e) {
    // environment failure: fail the request loudly, alert ops - do not retry in-process
    $logger->critical('CSPRNG failure on host ' . gethostname());
    throw new \RuntimeException('Secure random unavailable', 0, $e);
}

Prevention

When it happens

Trigger: openssl_random_pseudo_bytes() throwing or returning failure because: the openssl extension is loaded but broken/mismatched with the PHP version; the system entropy source is unavailable (chroot, restricted container, some minimal Docker images); OpenSSL FIPS/self-test failures; or rare older PHP bugs on exotic platforms.

Common situations: Heavily minimized container images (alpine variants missing proper openssl config), chrooted PHP-FPM without /dev/urandom access, or a PHP/OpenSSL ABI mismatch after partial package upgrades. Persistent occurrence usually indicates a broken PHP installation.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/0e56026729ecb5cf. Report an issue: GitHub.