Getting Started

Verify The Environment

Checking versions and confirming the exercises run on your machine.

Before you invest time in the exercises, it is worth confirming your machine will actually run them. Most reader frustration in this foundation traces back to one cause: the openssl command is not the OpenSSL 3.x you expected. A five-minute check now prevents commands that fail in confusing ways later.

Version checks and platform quirks

Start with the version of every tool the foundation uses.

openssl version
age --version
gpg --version | head -1

Expected output:

OpenSSL 3.3.2 24 Sep 2024 (Library: OpenSSL 3.3.2 24 Sep 2024)
v1.2.1
gpg (GnuPG) 2.4.5

The one that trips people up is OpenSSL on macOS. The system-provided /usr/bin/openssl is actually LibreSSL, a fork with a different feature set. Some commands used here (parts of pkeyutl, certain -pbkdf2 and provider behaviors) differ or are missing on LibreSSL.

SymptomLikely causeFix
openssl version says LibreSSLmacOS system binary on PATH firstPut openssl@3 ahead on PATH
unknown option '-pbkdf2'Old OpenSSL 1.xUpgrade to 3.x
pkeyutl rejects -rawinLibreSSL or OpenSSL below 3.0Install OpenSSL 3.x

Confirm which binary you are actually running:

which openssl
openssl version | grep -q "^OpenSSL 3" && echo "OK: OpenSSL 3.x" || echo "WRONG: not OpenSSL 3.x"

Expected output:

/opt/homebrew/opt/openssl@3/bin/openssl
OK: OpenSSL 3.x

If the last line says WRONG, revisit the PATH steps on the Local Setup page before going further.

A smoke-test script

This script exercises the same primitives the later pages rely on: random bytes, symmetric encryption round trip, hashing, and sign-and-verify. If it prints all checks passed, your environment is ready.

cat > ~/crypto-lab/smoke-test.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
cd "$(mktemp -d)"

# 1. randomness
openssl rand -hex 16 >/dev/null

# 2. symmetric round trip
echo "smoke test payload" > p.txt
openssl enc -aes-256-gcm -pbkdf2 -salt -in p.txt -out p.enc -pass pass:x
openssl enc -d -aes-256-gcm -pbkdf2 -in p.enc -pass pass:x | grep -q "smoke test payload"

# 3. hashing
openssl dgst -sha256 p.txt >/dev/null

# 4. sign and verify
openssl genpkey -algorithm ed25519 -out k.pem
openssl pkey -in k.pem -pubout -out k.pub
openssl pkeyutl -sign -inkey k.pem -rawin -in p.txt -out p.sig
openssl pkeyutl -verify -pubin -inkey k.pub -rawin -in p.txt -sigfile p.sig >/dev/null

echo "all checks passed"
EOF
bash ~/crypto-lab/smoke-test.sh

Expected output:

all checks passed

The set -euo pipefail line means the script stops at the first failure, so if you see anything other than all checks passed, the last command printed is the one to investigate.

Where to get help when a command differs

Command syntax drifts between OpenSSL releases, so when a command behaves unexpectedly, check your own build first rather than assuming the page is wrong.

  • openssl <subcommand> -help lists the exact flags your build supports, for example openssl pkeyutl -help.
  • man openssl-enc, man openssl-dgst, and friends document the version installed on your machine.
  • The OpenSSL project maintains a migration guide for the 1.x to 3.x transition, useful if a tutorial elsewhere uses old syntax.

When in doubt, compare the flags in the error against -help output; a missing or renamed flag is the usual culprit.

Practical Guidance

  1. Run openssl version first on any new machine and confirm it reports 3.x, not LibreSSL.
  2. On macOS, never assume /usr/bin/openssl; check which openssl and fix PATH if needed.
  3. Keep smoke-test.sh around and rerun it after any OpenSSL upgrade to catch regressions.
  4. When a command fails, read the actual error and check -help for your build before searching online.
  5. If a subcommand is genuinely missing, upgrade OpenSSL rather than hunting for a workaround; the exercises assume 3.x.