Skip to content

Document + pin ExtractPublicKey on-curve guarantee (closes #10) - #13

Merged
moisesja merged 1 commit into
mainfrom
docs/extract-publickey-oncurve-guarantee
Jun 14, 2026
Merged

Document + pin ExtractPublicKey on-curve guarantee (closes #10)#13
moisesja merged 1 commit into
mainfrom
docs/extract-publickey-oncurve-guarantee

Conversation

@moisesja

Copy link
Copy Markdown
Owner

Summary

Closes #10. JwkConverter.ExtractPublicKey already enforces the invalid-curve defense (it calls EcPointValidator.EnsureOnCurve on every EC point before returning), but the public contract never promised it. A consumer importing an attacker-supplied JWK — e.g. a JWE epk — and feeding the result into ICryptoProvider.DeriveSharedSecret therefore could not rely on the protection, and an undocumented behavior could silently regress.

This PR makes the existing guarantee contractual and pins it with a regression test. No behavior change — the validation was already in place.

Changes

  • JwkConverter.ExtractPublicKey XML doc now states the on-curve guarantee explicitly: every EC key type (P-256/P-384/P-521/secp256k1) is validated against the stated curve via EcPointValidator.EnsureOnCurve before returning, throwing CryptographicException for an off-curve / out-of-range / identity point (RFC 7518 §6.2.2; Antipa et al. 2003; Jager–Schwenk–Somorovsky 2015). OKP curves are a no-op (on-curve by construction). The CryptographicException/ArgumentException split is documented too.
  • Regression test ExtractPublicKey_ArbitraryForgedJwk_Throws (P-256/384/521/secp256k1): a fabricated, self-consistent JWK — valid coordinate lengths, (x, y) = (2, 3), not derived from any real point — is rejected at the import boundary. This is the genuine invalid-curve case the issue asks for, distinct from the existing bit-flip test (ExtractPublicKey_OffCurveJwk_Throws).
  • PRD FR-8 acceptance criteria record the guarantee.
  • CHANGELOG opens the [Unreleased] / 1.1.0 section; dev-default version bumped to 1.1.0 (release CI still derives the published version from the git tag).

Acceptance criteria (issue #10)

  • ExtractPublicKey rejects an off-curve EC JWK with CryptographicException — already enforced, now contractual.
  • XML doc states the on-curve guarantee.
  • Test covers a forged-but-self-consistent EC JWK whose coordinates do not satisfy the curve equation.

Verification

  • dotnet build -warnaserror clean.
  • JWK + EC-point-validator suites green (75 tests), including the 4 new fabricated-point cases.

🤖 Generated with Claude Code

JwkConverter.ExtractPublicKey already validates EC (x, y) against the stated
curve via EcPointValidator.EnsureOnCurve before returning, but the public
contract never promised it. A downstream caller importing an attacker-supplied
JWK (e.g. a JWE epk) and feeding it to DeriveSharedSecret could not rely on the
invalid-curve defense (RFC 7518 §6.2.2) being applied.

- State the on-curve guarantee explicitly in the ExtractPublicKey XML doc, incl.
  the CryptographicException contract for off-curve / out-of-range / identity points.
- Add a regression test using a *fabricated, self-consistent* JWK (valid coordinate
  lengths, (x,y)=(2,3), not derived from any real point) — the genuine invalid-curve
  case, distinct from bit-flipping a legitimate point — across P-256/384/521/secp256k1.
- Record the guarantee in the FR-8 acceptance criteria (PRD).
- Start the 1.1.0 CHANGELOG section; bump the dev-default version to 1.1.0
  (release CI still derives the published version from the git tag).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@moisesja moisesja added this to the 1.1.0 milestone Jun 14, 2026

@moisesja moisesja left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me — clean, well-scoped, and low-risk. ✅ (Posting as a comment since GitHub won't let me formally approve this account's own PR.)

Verified the central claim. The PR asserts "no behavior change — the validation was already in place," and the source confirms it: JwkConverter.ExtractPublicKey already calls EcPointValidator.EnsureOnCurve(keyType, x, y) (JwkConverter.cs:110) on the decoded coordinates before reconstructing the SEC1 point and returning, for every EC key type. The new XML doc, PRD FR-8 criterion, and changelog entry all describe this existing behavior accurately — they make an undocumented guarantee contractual rather than changing it.

The regression test is the right test. ExtractPublicKey_ArbitraryForgedJwk_Throws uses correctly-sized but fabricated (x, y) = (2, 3) coordinates that decode cleanly (so they reach EnsureOnCurve) yet don't satisfy the curve equation — the genuine "attacker mints an epk from scratch" case, and meaningfully distinct from the existing bit-flip test. Covering all four EC curves (P-256/384/521/secp256k1) matches the documented scope.

Minor, non-blocking observations (no change required):

  • The changelog's [Unreleased] heading references #10/#11/#12 as the 1.1.0 target, but this PR only delivers #10. Fine for an Unreleased rollup; just flagging so the section doesn't read as if all three landed here.
  • The dev-default version bump to 1.1.0 is appropriate given the comment notes release CI derives the published version from the git tag.

CI: macOS and the no-native (BBS-absent) job are green; Windows/Ubuntu were still in progress at review time (the only reason the PR shows unstable). Worth a glance before merge, but nothing in this diff suggests a platform-specific risk.


Generated by Claude Code

@moisesja moisesja self-assigned this Jun 14, 2026
@moisesja
moisesja merged commit 544b313 into main Jun 14, 2026
4 checks passed
@moisesja
moisesja deleted the docs/extract-publickey-oncurve-guarantee branch June 14, 2026 17:57
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.

Guarantee + document EC on-curve validation in JwkConverter.ExtractPublicKey (invalid-curve defense)

1 participant