Chapters · Chapter 15

The Geometry Is the Encryption

Part VI — Gauge Encryption · seven builds, seven receipts

The chapter's exercises are gauge-invariance receipts on real bytes — instrument the five modes, reproduce the six-slot tuple under a rotation, forge an attacker who tries to slide under the \(10^{-10}\) grain, and benchmark the cost of the inverse-shift at the client. Receipt class is byte-equality after gauge, drift below quantization, and HMAC verify/refuse on tampered bundles.

Run it live — GQL console

Point at the public read-only instance (no key needed) or your own engine (start it with GIGI_CORS_ORIGIN=* for browser access — dev only).

E15.1Reproduce the six-slot invariant under a per-field affine rotation

Build

Write an integration test that loads any nondegenerate numeric bundle, computes InvariantTuple via src/integrity.rs:130-145, then re-encrypts every field with a fresh FieldTransform::Affine {scale, offset} pair sampled per column (\(a_i \neq 0\)), and re-reads the tuple from the gauged bundle.

Receipt

The three u64 slots (record_count, beta_0, beta_1) are bit-identical, and the three f64 slots (\(K\), \(\lambda_1\), holonomy_mean) agree to relative error \(<10^{-10}\) — the same grain quantize_f64 uses at src/integrity.rs:51-66. Asserts pass; this is the empirical leg of my Theorem 3.6 in Davis 2026.

Bonus

Sweep \(|a_i|\) across \([10^{-3}, 10^{3}]\) and plot the post-gauge drift of \(K\) versus the magnitude of the scale factor. The drift floor is the quantizer; if you see it rise, you found a numerical issue worth filing.

E15.2Refute the off-diagonal gauge on a covariance-bearing bundle

Build

Forge a hand-rolled FieldTransform variant that takes a \(2\times 2\) block \(A\) with \(A_{12} \neq 0\) instead of two scalars, apply it to a bundle whose columns have nonzero \(\mathrm{Cov}(v_i, v_j)\), and recompute the per-field \(K\)-vector.

Receipt

The post-gauge \(K_i\) disagrees with the plaintext \(K_i\) on the constructed bundle — the explicit witness for the necessity half of Proposition 3.7. Log the disagreement to a fixture and tag it as the canonical "why the engine has no \(k\times k\) slot at src/crypto.rs:Affine" receipt.

Bonus

Try the pure rotation case \(A = O \in O(2)\). Confirm \(\mathrm{tr}(\mathrm{Cov})\) survives while the per-field ratio breaks — the trace-vs-ratio asymmetry I called out in the proposition closer.

E15.3Stress the Curvature-MAC against Eve's sub-grain edit

Build

Reproduce my Appendix A.12 worked example end-to-end: mint a tag \(t = \mathrm{HMAC\text{-}SHA256}_{k_{\mathrm{int}}}(\mathrm{canonical\_bytes}(\pi_{\mathrm{inv}}))\) via sign at src/integrity.rs:218-230, ship the bundle plus tag, then have a sibling process flip bits in record 7's age field at three perturbation magnitudes: \(10^{-12}\) (sub-grain), \(10^{-9}\) (above grain), \(10^{-3}\) (gross).

Receipt

verify at src/integrity.rs:243-253 returns true on the \(10^{-12}\) edit, false on the \(10^{-9}\) edit, and false on the \(10^{-3}\) edit. Three test cases, three assertions, one of them deliberately the honest miss. The honest miss is the receipt that the Holonomy ledger is doing complementary work and is not redundant.

Bonus

Time the verify path on a 1M-record bundle. It should be flat in record count — the HMAC reads 52 bytes, not the bundle.

E15.4Instrument the five-mode count across three surfaces

Build

Write a CI check that parses the variant list from src/types.rs:180-199 (excluding None), the mode rows from GIGI_API.md:1579-1587, and the row count of Table 1 in theory/encryption/paper_geometric_encryption_v0.1.tex:983-1002, then asserts all three return the set \(\{\)Affine, Opaque, Indexed, Probabilistic, Isometric\(\}\).

Receipt

A failing test the day any future contributor adds a sixth mode to one surface without touching the other two — the same drift that produced the chapter 1 five-not-six error caught at parse time instead of in the corrigendum.

Bonus

Wire the check into the pre-commit hook so the three surfaces cannot diverge between commits.

E15.5Benchmark the AFFINE workhorse's twelve aggregates

Build

On a 100k-record numeric bundle, run all twelve \(\rho\)-equivariant aggregates from my §3.3 (SUM, AVG, MIN, MAX, VAR, STDDEV, RANGE, MEDIAN, QUANTILE, ARGMIN, ARGMAX, COUNT) on plaintext and on the AFFINE-gauged ciphertext. Apply the client-side \(\rho_g^{-1}\) inversion per aggregate.

Receipt

Twelve pairs of returned scalars equal to within \(10^{-10}\). The server-side timing is within \(\pm5\%\) of plaintext — the receipt that AFFINE costs nothing at native speed — and the client-side inverse is \(O(1)\) per query, measured. The 24 unit tests in src/aggregate_helpers.rs are the regression net; this exercise adds the timing receipt those tests do not.

Bonus

Repeat on a 10M-record bundle. The client-inverse cost stays flat; the server cost scales linearly. If either changes shape, you found the implementation drift Theorem 3.3 clause (c) forbids.

E15.6Extend ISOMETRIC: verify the kNN graph survives rotation

Build

Declare a GROUP of three numeric fields under ENCRYPTED ISOMETRIC, build the all-pairs distance matrix and its \(k\)-nearest-neighbour adjacency on plaintext, then on ciphertext via the \(O \in O(3)\) gauge derived by derive_orthogonal_matrix at src/crypto.rs.

Receipt

The two adjacency matrices are bit-identical at every \(k \in \{1, 3, 5, 10\}\). Distances themselves agree to \(10^{-12}\) — ISOMETRIC's invariant ring is the distance ring, and this is the empirical demonstration that \(\lambda_1\) and the Fiedler partition land identically on plaintext and ciphertext.

Bonus

Replace \(O\) with a non-orthogonal invertible matrix you forged by hand. Watch the kNN adjacency drift and file the diff as the “why ISOMETRIC type-checks the GROUP declaration” receipt.

E15.7Wire the constant-time verify into a timing harness

Build

Submit one million forged tags to verify at src/integrity.rs:243-253, varying how many leading bytes of each forgery match the real tag. Record per-call wall-time at nanosecond resolution.

Receipt

The distribution of verify-times is statistically indistinguishable across the leading-match-count groups (Kolmogorov-Smirnov \(p > 0.05\)). The receipt that mac.verify_slice is doing the constant-time compare the doc-comment promised, not the naive short-circuit a byte-by-byte loop would have done.

Bonus

Swap verify_slice for a hand-rolled == on the tag bytes and rerun. The KS test should now reject; you have just measured the side channel the constant-time compare closes.

← Chapter 14 exercisesChapter 16 exercises →