Keys and operations

Generate keys securely

Use cryptographically secure platform or key-management APIs with the exact size and algorithm required instead of deriving keys from memorable text.

Cryptographic keys need enough unpredictable bits. A 256-bit key is only as strong as 256 bits if every bit came from a source an attacker cannot model. Human-created phrases and ordinary random functions do not provide that.

Math.random() is the classic mistake in JavaScript. It exists for shuffling animations, not secrets: it is not a CSPRNG (cryptographically secure pseudorandom number generator), and its outputs can be predicted from previous outputs. The same goes for timestamps, process IDs, and anything else an attacker can guess or observe.

Use the platform’s secure source

Let a maintained library, operating system, HSM, or KMS generate keys. In Node, node:crypto reads from the operating system’s CSPRNG:

import { randomBytes } from 'node:crypto'

const key = randomBytes(32)

That is a full-strength 256-bit key. On the command line, openssl does the same job:

openssl rand -hex 32
# 41d1e2c7a80f5b9e6d3c7f2a1b8e4d90c5a6f3e2d1b0a9c8e7f6d5c4b3a29180

Match the exact size and algorithm the construction requires: 32 bytes for AES-256, 12 bytes for a GCM nonce, key pairs through generateKeyPairSync rather than raw bytes. For random integers and identifiers, use randomInt() and randomUUID() from the same module, never Math.random().

Why derived-from-text keys fail

A developer derives an encryption key with SHA-256 from a memorable deployment phrase. The output looks perfectly random — 64 hex characters, passes every eyeball test. But an attacker who obtains ciphertext can test likely phrases offline much faster than searching a random key space. The key space collapsed from 2^256 to “phrases a person would pick.”

Use a password KDF only when a user password must derive key material — an unavoidable input, like encrypting a local vault with the user’s passphrase. Then use a real password KDF with a salt and current parameters, never a bare hash, and accept that the key is only as strong as the password.

Two operational rules. Never print generated keys while debugging: logs outlive the debugging session and flow into systems with wider access. And if key generation fails, it must fail loudly — a fallback to a timestamp-seeded generator is a silent catastrophe.

Practice

Trace the generation API and random source for every key in one small application, and save algorithm plus length metadata without saving key bytes. Generate two keys and prove they differ and satisfy the library format. Then block or mock the random source and confirm generation fails instead of falling back to a timestamp or ordinary random function.

Lesson completed

Take this course offline

Get every free book, course edition, and software download.

Get the download library →