GCD: Garbled, Corrected, Demonstrandum -- Fixing and Proving Go's Extended GCD Implementation
Linard Arquint
cs.CR
Jun 4, 2026 · v1
TL;DR
Lean proves key non-linear arithmetic lemmas that are imported into the Gobra verifier for Go's extended-GCD code.
Abstract
We verify the 'extendedGCD' implementation in Go's standard library ('crypto/internal/fips140/bigmod'), which plays a crucial role in the generation of RSA key pairs. Even though the Go implementation is supposedly a direct port from BoringSSL's implementation, we uncovered two deviations that each break the algorithm's invariants: (1) the Go implementation deviates in the way coefficients are updated, and (2) it permits a larger input domain. We address both deviations; the first by fixing the Go implementation, which results in an on average 24% speedup, and the second deviation by porting an existing proof for BoringSSL and extending it to cover the larger input domain. We prove correctness and termination of the fixed Go implementation using Gobra, a deductive program verifier for Go. Where necessary, we used Lean to prove key lemmata on non-linear arithmetic, which we import into Gobra. Our verification effort reveals three key insights: subtle bugs can slip into even well-reviewed code with surprising ease; formal verification is a powerful tool for uncovering them; and AI agents can facilitate the verification process by iteratively refining invariants and lemmata based on Gobra's error messages.
Problem
Go's standard library extended GCD implementation (crypto/internal/fips140/bigmod), critical for RSA key generation, claims to be a direct port of BoringSSL's implementation. Despite review by three developers, subtle deviations from the original algorithm went undetected.
Approach
The authors verify Go's extendedGCD using Gobra, a deductive program verifier for Go. They uncovered two deviations that each break the algorithm's invariants: unsynchronized coefficient reductions and a larger input domain than BoringSSL permits. They fix the first deviation in the Go code and extend an existing Rocq proof for BoringSSL to cover the larger domain. Lean is used to prove key lemmata on non-linear arithmetic, which are imported into Gobra.
Results
The fix to the unsynchronized subtraction deviation yields an average 24% speedup. The full verified implementation comprises 149 lines of Go code and 838 lines of Gobra specifications/proofs. AI agents were used to iteratively refine invariants and lemmata based on Gobra error messages.
| Function | LOC | LOS |
|---|
| extendedGCD | 53 | 99 |
| InverseVarTime | 10 | 18 |
| GCDVarTime | 7 | 12 |
| syncAdd | 8 | 60 |
| Other Go functions | 71 | 314 |
| Lemmata | - | 349 |
| Total | 149 | 838 |
Verification effort breakdown