Appendix C: Environment setup
Every code block in this book runs on a stock CPython install at version 3.10 or newer. Most chapters use only the standard library. The code blocks in Chapters 7 through 12, and in the Appendix D solutions for Chapter 7, also require NumPy 1.26 or newer; every other chapter is stdlib-only. No other third-party package is assumed at any point. If a block in the book fails on a machine that satisfies those two constraints, that is a bug in the book, and the chapter commit is not supposed to land.
This appendix is the contract Chapter 4 refers to when it notes that simulating the quantum period-finding step of Shor’s algorithm honestly would require Qiskit, Cirq, or stim and break the clean-install rule. The rest of this appendix explains how to satisfy that contract.
What you need installed
Section titled “What you need installed”Two pieces of software, both standard:
- CPython 3.10 or newer. The pedagogical code uses
matchstatements and PEP 604 union syntax, both of which require 3.10. Any point release in the 3.10, 3.11, 3.12, or 3.13 series is fine. On Debian and Ubuntu the package ispython3; on macOS the Homebrew package ispython@3.12; on Windows the official installer at python.org ships a recent CPython. - git. The companion code repository is at
https://github.com/Encryptorium/book-of-pqc-code. Any recent git release works.
There is no Node.js, no Docker, no SageMath, no Rust toolchain on the reader path. The Astro site and the PDF build use Node.js and Pandoc, but those are author-side tools; readers never have to run them.
Clone the repository
Section titled “Clone the repository”git clone https://github.com/Encryptorium/book-of-pqc-code.gitcd book-of-pqc-codeThe book publishes one chapter at a time, and a chapter’s code publishes with it. The repository holds the packages for the chapters released so far rather than the full set, so expect it to grow as the book does.
The layout:
code/chNN-<slug>/is a standalone Python package for one chapter.tests/chNN/is the matching pytest suite, including the NIST vector comparisons where a chapter has them.
The prose, figures, and exercise solutions are not in this repository. They are published at book.encryptorium.com.
Create a fresh virtual environment
Section titled “Create a fresh virtual environment”python3 -m venv .venvsource .venv/bin/activateOn Windows PowerShell the activation line is .venv\Scripts\Activate.ps1 instead.
After activation, pip list on an upstream CPython 3.12 or newer venv shows only pip. CPython 3.10 and 3.11 also install setuptools into a new venv, and some distribution-patched builds include setuptools (or wheel) on any version. Either output is correct: pip builds each code/chNN-* package in an isolated PEP 517 environment, so a setuptools already present in the venv is inert during the install. One external dependency is required for the book’s 30 code packages: NumPy 1.26 or newer, and only for five of them (the packages for Chapters 7, 8, 9, 10, and 11). Every other package installs against the standard library alone.
How the code blocks are verified
Section titled “How the code blocks are verified”Every code block in the chapter prose carries a # ==> expected-output marker. A gate in the book’s continuous integration extracts each fenced Python block, runs it in isolation, and compares stdout against those markers. A block with no marker is still executed, so a syntax error or a runtime exception still fails the gate; it just has no output assertion. A block tagged no-verify is skipped, for the rare case where the snippet is a sketch not meant to run standalone.
That gate reads the chapter Markdown, so it runs where the prose lives rather than in the code repository. What you can run yourself is each chapter’s pytest suite, described next. Between the two, every code block printed in the book has been executed, and the package it was cut from has been tested.
Run a chapter’s pytest suite
Section titled “Run a chapter’s pytest suite”Each package under code/chNN-<slug>/ installs as a standard Python module and ships with a pytest suite at tests/chNN/. Pytest itself is not part of the standard library and is not declared as a dependency of any chapter’s package, since the chapters’ runtime code never imports it. Install pytest once into the venv before running any test suite:
pip install pytestThen install and test one chapter:
pip install -e code/ch16-slh-dsapytest tests/ch16 -xFor the flagship implementations, test_vectors.py under the chapter’s test directory checks package output against the official NIST Algorithm Validation (ACVP) vectors byte-for-byte. For ML-KEM (Chapter 11), keygen, encapsulation, and decapsulation each compare against ACVP vectors. For SLH-DSA (Chapter 16), keygen compares against ACVP vectors across all twelve parameter sets and signing is verified by deterministic sign-verify round-trips at the 128f parameter sets. A clean run ends with passed against every assertion. If a vector fails, the book’s implementation diverged from the published specification, and that is a bug.
Installing a chapter’s package does not pull in anything new for stdlib-only chapters. Chapters 7 through 11 install numpy as a dependency; see the next section.
Part II addendum: NumPy for Chapters 7 through 11
Section titled “Part II addendum: NumPy for Chapters 7 through 11”The lattice chapters (Chapter 7 through Chapter 11) represent Module-LWE secrets, public keys, and ciphertexts as NumPy integer arrays. The pedagogical cost of a pure-Python implementation is that the linear-algebra content disappears inside hand-rolled loops, and the Module-LWE matrix-vector products become the dominant runtime in any full vector check. NumPy keeps both the prose and the run-time compact without adding any abstraction the reader cannot follow.
To run those chapters, install NumPy inside the venv:
pip install "numpy>=1.26"This is the only third-party dependency any chapter in the book introduces. Installing a Part II package with pip does this automatically:
pip install -e code/ch11-mlkemAfter the install, pip list shows numpy at a version 1.26 or newer. The Chapter 12 package (lattice cryptanalysis) is stdlib-only: it uses Python’s math module for the closed-form root-Hermite-factor cost estimate and declares no dependencies. The chapter itself still needs NumPy, for the toy LLL block that runs the Kannan embedding.
Quantum simulators are out of scope
Section titled “Quantum simulators are out of scope”Chapter 4 builds toy RSA and toy ECDSA from scratch and then walks the classical post-processing of Shor’s algorithm on a 9-bit modulus in a few lines of gcd arithmetic. What the chapter deliberately does not do is simulate the quantum period-finding subroutine. Simulating a useful Shor circuit classically is itself exponential in the qubit count, and running it honestly needs a dedicated quantum simulator such as Qiskit, Cirq, or stim. Pulling any of those into the reader’s venv would move the chapter’s focus from classical post-processing to simulator setup, which is a different book.
If you want to see the quantum part end-to-end, the original Shor paper (Shor, 1994) and the Nielsen and Chuang textbook (Nielsen & Chuang, 2010) walk the circuit in full. The book references both at the point where the classical slice ends.
Smoke test
Section titled “Smoke test”Once Python is installed and the venv is active, this block confirms the environment:
import hashlib
sha = hashlib.sha256(b"book-of-pqc setup ok").hexdigest()[:16]print(sha)# ==> e0ae8dc9e81b9052The printed prefix is e0ae8dc9e81b9052 on every CPython release in the 3.10 through 3.13 series. If the hash differs, the venv is not active or a different interpreter is running; check python3 --version and which python3.
Common setup issues
Section titled “Common setup issues”A few things that trip readers up most often.
”No module named ‘numpy’” in a Part II chapter
Section titled “”No module named ‘numpy’” in a Part II chapter”The venv is active but numpy was not installed. Run pip install "numpy>=1.26" inside the venv and retry.
Pytest reports “no tests ran”
Section titled “Pytest reports “no tests ran””The package was not installed into the venv. Run pip install -e code/chNN-<slug> before calling pytest.
python3 --version reports 3.8 or 3.9
Section titled “python3 --version reports 3.8 or 3.9”The match statements in several chapters will raise a SyntaxError. Install CPython 3.10 or newer; if a system package manager pins an older version, the official CPython installer at python.org bypasses that pin cleanly.
The venv activates but which python still points at the system CPython
Section titled “The venv activates but which python still points at the system CPython”The shell cached the pre-venv path. Open a new shell, cd into the repository, activate again.
A chapter’s code block runs in the book but fails when pasted into a REPL
Section titled “A chapter’s code block runs in the book but fails when pasted into a REPL”The verification gate runs each block in a fresh interpreter; variables from earlier blocks do not leak into later ones. If a chapter splits a computation across two blocks, the second block restates the variables it needs, and the REPL needs the same.
Exit condition
Section titled “Exit condition”A reader following the steps above has a venv with CPython 3.10 or newer, a fresh clone of the code repository, and (for the lattice chapters) NumPy 1.26 or newer. Running pytest tests/ from the repository root should report every test passing, with no diagnostic output. From that point, every published chapter’s code is reproducible.