Commit 456a1da
proof(SafeCrypto): annotate 15 bodyless decls as OWED (Refs standards#158) (#60)
## Summary
Converts the **15 bodyless declarations** in
`src/Proven/SafeCrypto/Proofs.idr` from the legacy `export <sig>`
postulate form (with prose-only `-- |` comments) into the estate
**OWED-with-justification** convention established by
`Proven.SafeChecksum.Proofs` (and now SafeAPIKey #37, SafeMath #46,
SafeTOML #52, SafeOTP #50, SafeCSRF #53, SafeString #54, ...):
triple-pipe `||| OWED:` docstring + `0 ` erased-multiplicity + bare sig.
No `postulate`, no `believe_me`, no `idris_crash`.
Refs hyperpolymath/standards#158.
## Classification
**SafeCrypto's prompt flagged that this is a crypto module — many decls
may be permanent class-J hardness axioms. Audit result: 0/15.**
| Category | Count | Notes |
|---|---:|---|
| Pure cryptographic-hardness axioms (class-J, *never* in pure Idris2 —
collision resistance, preimage resistance, etc.) | **0** | None present.
Would live in a separate `Assumptions.idr` parallel to proof-of-work's
I6 `sha256CollisionResistant`. |
| `Data.Bits` primitive opacity (xor / xor-commutativity /
xor-cancellation / shiftR-cast round-trip — real discharge path via
stdlib lemma) | **6** | `constantTimeRefl`, `constantTimeSym`,
`digestEqRefl`, `digestEqSym`, `differentDigestsUnequal`,
`counterNonceUnique` |
| `String` FFI opacity (pack/unpack/length — same family as SafeChecksum
Luhn/ISBN, SafeBuffer pack) | **3** | `tokenLengthApprox`, `uuidLength`,
`hexEncodeEvenLength` |
| Random-generation FFI opacity (OS entropy `getEntropy`/`/dev/urandom`)
| **4** | `randomBytesLength`, `randomNatBounded`, `randomRangeBounded`,
`freshNonceSize` |
| `case`-on-abstract-algorithm reduction wall (`isSecure alg = case
securityLevel alg of ...` won't reduce for abstract `alg` even with
rewrite in scope) | **2** | `modernIsSecure`, `standardIsSecure` |
Every entry has a **named blocker** and a **named discharge condition**
in its `||| OWED:` docstring — discoverable by `grep "OWED" src/`, not
silent.
## Per-decl summary
### Constant-time / digest comparison (5)
- `constantTimeRefl : (d : ByteVector n) -> digestEq d d = True` — needs
`Data.Bits` `xor x x = 0` lemma.
- `constantTimeSym : (d1, d2 : ByteVector n) -> digestEq d1 d2 =
digestEq d2 d1` — needs `Data.Bits` `xorCommutative`.
- `digestEqRefl` / `digestEqSym` — same claims as `constantTime*`
(API-discoverability duplicates); discharge together.
- `differentDigestsUnequal : ... Not (d1 = d2) -> digestEq d1 d2 =
False` — needs the `Data.Bits` cancellation lemma `xor x y = 0 -> x =
y`, plus an induction over `Vect n`.
### Security-level case-analysis (2)
- `modernIsSecure : ... securityLevel alg = Modern -> isSecure alg =
True`
- `standardIsSecure : ... securityLevel alg = Standard -> isSecure alg =
True`
Both block on the same `case`-under-abstract-scrutinee reduction wall:
`isSecure alg = case securityLevel alg of ...` will not reduce under an
abstract `alg : HashAlg` even after `rewrite` substitutes the scrutinee,
because the `case` was not eta-expanded to a generalised motive at
elaboration. **Real fix:** refactor `isSecure` in `SafeCrypto.Hash` to a
top-level pattern-match dispatch on `securityLevel` — then both proofs
close by `Refl` after `rewrite`.
### Random-generation FFI bounds (3)
- `randomBytesLength`, `randomNatBounded`, `randomRangeBounded` — all
hit the OS entropy FFI (`getEntropy` / `/dev/urandom`) which is opaque
to 0.8.0's type-level reducer. `randomNat` further hits the `Integral
Nat` `mod` blocker that `SafeChecksum.Proofs` already documents for
`sumChecksum`.
### Nonce + UUID (3)
- `counterNonceUnique` — encoding injectivity through Bits64 → 4-byte
big-endian; needs `Data.Bits` `shiftR`/`cast` round-trip lemmas.
- `freshNonceSize` — literally `randomBytesLength` lifted through the
`freshNonce = randomBytes` rename; discharge together.
- `uuidLength` — `pack [...]` over a fixed-shape list; needs `String`
pack/length lemma.
### Token + hex even-length (2)
- `tokenLengthApprox` — base64 expansion bound over `String` FFI
`pack`/`unpack`/`Bits8 -> Char`.
- `hexEncodeEvenLength` — even-length output of a parametric hex
encoder; blocked both by the parametric signature (no per-byte
hypothesis available) and by `String` FFI opacity even when specialised.
Discharge requires (a) tightening the sig to the concrete
`Proven.SafeCrypto.bytesToHex` AND (b) the `String`-FFI reflective
tactic.
## Form (matches SafeChecksum / sibling PRs convention)
```idris
||| OWED: <claim restated>
||| <Idris2 0.8.0 blocker, by name>
||| Discharge once <unblocker>.
public export
0 <name> : <original signature>
```
- Triple-pipe doc block
- Leading `0 ` (erased-multiplicity, runtime-stripped)
- Original bare signature otherwise unchanged
- No `postulate`, no `believe_me`, no `idris_crash`
- Matches `Proven.SafeChecksum.Proofs` L24–L100 reference pattern
## Phase 1 attempt
Each OWED docstring names the *specific* blocker that prevents a real
`Refl`/`rewrite` discharge today, and the *specific* unblocking
condition. Highlights:
- `modernIsSecure` / `standardIsSecure` are the closest to dischargeable
today — the only structural obstacle is that `isSecure` is defined as an
internal `case` rather than a top-level pattern-match; a 3-line refactor
in `SafeCrypto.Hash` would let both close by `Refl` after the supplied
rewrite. Filed as the named discharge condition rather than as a
parallel change in this PR (keeps the diff to `Proofs.idr`-only per the
campaign rule "Do NOT touch other files").
- The Bits-family and Random-family blockers re-verify the same
`Data.Bits` and entropy-FFI opacity that `SafeChecksum` already
documents; no new defect surfaced.
## Verification
```
$ idris2 -p base -p contrib --source-dir src --check src/Proven/SafeCrypto/Proofs.idr
1/4: Building Proven.Core (src/Proven/Core.idr)
2/4: Building Proven.SafeCrypto.Hash (src/Proven/SafeCrypto/Hash.idr)
3/4: Building Proven.SafeCrypto.Random (src/Proven/SafeCrypto/Random.idr)
4/4: Building Proven.SafeCrypto.Proofs (src/Proven/SafeCrypto/Proofs.idr)
$ echo $?
0
```
`Proven.SafeCrypto.Proofs` builds green together with its dependencies
under Idris2 0.8.0.
## Scope
- Touches **only** `src/Proven/SafeCrypto/Proofs.idr`.
- 15 declarations annotated; the 9 already-discharged `Refl` proofs in
the file (`sha256OutputSize`, `sha512OutputSize`, `sha3_256OutputSize`,
`blake3OutputSize`, `sha256Secure`, `sha512Secure`, `sha3_256Secure`,
`md5NotSecure`, `sha1NotSecure`, `hexEncodeDeterministic`) are
untouched.
- No callers outside this file; the other
`constantTimeRefl`/`constantTimeSym` matches across the tree are
namespaced-local distinct symbols in `SafeDigest` / `SafePassword`.
## Why draft
Filed DRAFT per the convention (estate-wide proven CI queue jam, cf.
sibling PRs #46/#52/#53). Owner to promote from DRAFT once the pool
clears.
## Test plan
- [x] `idris2 -p base -p contrib --source-dir src --check
src/Proven/SafeCrypto/Proofs.idr` -> exit 0.
- [x] No callers regression: grep clean for all 15 names outside
Proofs.idr.
- [x] Branch rebased on latest `origin/main` (after #51/#52/#53/#54
landed).
- [ ] Owner-side: ratify against any in-flight SafeCrypto edits before
merging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 76951a8 commit 456a1da
1 file changed
Lines changed: 211 additions & 94 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
7 | 25 | | |
8 | 26 | | |
9 | 27 | | |
| |||
26 | 44 | | |
27 | 45 | | |
28 | 46 | | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
43 | 71 | | |
44 | 72 | | |
45 | 73 | | |
| |||
94 | 122 | | |
95 | 123 | | |
96 | 124 | | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
107 | 140 | | |
108 | 141 | | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
109 | 152 | | |
110 | 153 | | |
111 | 154 | | |
112 | 155 | | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
120 | 163 | | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
129 | 183 | | |
130 | 184 | | |
131 | 185 | | |
132 | 186 | | |
133 | 187 | | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
153 | 220 | | |
154 | 221 | | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
155 | 234 | | |
156 | 235 | | |
157 | 236 | | |
158 | 237 | | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
173 | 262 | | |
174 | 263 | | |
175 | 264 | | |
176 | 265 | | |
177 | 266 | | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
183 | | - | |
184 | | - | |
185 | | - | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
192 | 296 | | |
193 | 297 | | |
194 | 298 | | |
| |||
211 | 315 | | |
212 | 316 | | |
213 | 317 | | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
0 commit comments