Skip to content

Dispose generated KeyPair in DidKeyMethod/Numalgo0Handler (ND-E8 follow-up)#99

Merged
moisesja merged 3 commits into
mainfrom
claude/github-issue-97-b20117
Jul 13, 2026
Merged

Dispose generated KeyPair in DidKeyMethod/Numalgo0Handler (ND-E8 follow-up)#99
moisesja merged 3 commits into
mainfrom
claude/github-issue-97-b20117

Conversation

@moisesja

Copy link
Copy Markdown
Owner

Fixes #97

What

NetCrypto 1.2.0 made KeyPair IDisposable (deterministic zeroization of the pinned private-key copy). The two fresh-key create paths flagged in #97 generated a KeyPair, read only its public key, and orphaned the private half to the GC unwiped. Both now dispose the pair as soon as the public key is copied out:

  • DidKeyMethod.CreateCoreAsyncsrc/NetDid.Method.Key/DidKeyMethod.cs
  • Numalgo0Handler.Createsrc/NetDid.Method.Peer/Numalgo0Handler.cs

KeyPair.PublicKey defensively copies on get (verified against the NetCrypto 1.2.0 docs and empirically), so created DIDs and documents are byte-identical to main. ExistingKey (ISigner) and IKeyStore custody paths are untouched. Grep-verified these are the only two Generate(...) call sites in src/.

Tests (fail-first)

16 new regression tests: Issue97_Create_FreshKey_DisposesGeneratedKeyPair and Issue97_Numalgo0_FreshKey_DisposesGeneratedKeyPair, theories over all 8 supported key types per method. A recording IKeyGenerator fake (hand-rolled — NSubstitute can't intercept ReadOnlySpan params) captures the generated pair plus an independent clone of its public key; each test asserts the pair throws ObjectDisposedException after create, the snapshot is non-zero, and the resulting DID encodes the pre-disposal key. With the fix stashed, all 16 fail (8/8 per project); mutation-tested independently during review with the same result.

Verification

  • Release build: 0 warnings, 0 errors
  • Full suite: 989 green — Core 374, Method.Key 52, Method.Peer 48, Method.WebVh 326, DI 14, W3C conformance 175 (100%)
  • All 4 samples exit 0; git diff --check clean

Adversarial review

Three independent red-team passes (lifecycle/use-after-dispose, scope completeness, contract/test validity). No defect confirmed in the change; empirical probes covered defensive-copy integrity, dispose idempotency on exception unwind, and a 20k-iteration torn-read race (0 torn reads). Two Low findings were fixed in the second commit: the CHANGELOG's "no behavior change" claim is now scoped to conforming IKeyGenerator implementations (a generator that retains the returned pair now observes it disposed — permitted by NetCrypto's ownership contract), and the test snapshot no longer aliases the getter under test.

Notes

  • No NetDidVersion bump (release-PR concern); CHANGELOG entry under [Unreleased] → Security.
  • Milestone 2.3.0 per the issue.

🤖 Generated with Claude Code

moisesja and others added 3 commits July 12, 2026 22:07
NetCrypto 1.2.0 made KeyPair IDisposable with deterministic zeroization.
DidKeyMethod.CreateCoreAsync and Numalgo0Handler.Create now dispose the
pair they generate and discard, instead of orphaning the pinned private
key to the GC unwiped. PublicKey is defensively copied on get, so the
DID built from the pre-disposal copy is unchanged.

Issue97_* regression theories cover all 8 supported key types per
method via a recording IKeyGenerator fake (fail-first proven: 8/8 fail
per project without the fix).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…claim

Review confirmed two Low findings: (1) the CHANGELOG "no behavior
change" claim was false for custom IKeyGenerator implementations that
retain the returned KeyPair — reworded to state the ownership contract;
(2) the test fake recorded the public key via the same getter under
test, so a defensive-copy regression would alias the snapshot and pass
zeros-to-zeros — the fake now clones the recorded key and the theories
assert the snapshot is non-zero.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@moisesja
moisesja force-pushed the claude/github-issue-97-b20117 branch from 4c402a1 to 2789352 Compare July 13, 2026 02:14
@moisesja moisesja self-assigned this Jul 13, 2026
@moisesja moisesja added this to the 2.3.0 milestone Jul 13, 2026
@moisesja
moisesja merged commit be199fd into main Jul 13, 2026
1 check passed
@moisesja
moisesja deleted the claude/github-issue-97-b20117 branch July 13, 2026 02:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dispose generated KeyPair in DidKeyMethod/Numalgo0Handler now that NetCrypto 1.2.0 makes it IDisposable (ND-E8 follow-up)

1 participant