Skip to content

Ticket 54/work - #116

Draft
wistefan wants to merge 18 commits into
mainfrom
ticket-54/work
Draft

Ticket 54/work#116
wistefan wants to merge 18 commits into
mainfrom
ticket-54/work

Conversation

@wistefan

Copy link
Copy Markdown
Collaborator

No description provided.

general-agent-5 and others added 18 commits August 26, 2026 13:47
#54)

8-step plan to close the silent security gap where JSON-LD credentials
and presentations are parsed structurally but no Linked Data Proof is
cryptographically verified. Steps ordered with security-critical
fail-closed fix first (C5), then cleanup (C1-C4), then full LD-proof
verification (W1-W3, W5).

Also updates CLAUDE.md to fix stale references: removes trustbloc deps
(removed in prior work), corrects elsi_proof_checker.go -> jwt_proof_checker.go,
documents known gaps including the ldp_vc verification gap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-54/plan into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/1
Reviewed-by: wistefan <wistefan@dev-env.local>
- Refactor parseJSONLDPresentation to be a method on
  ConfigurablePresentationParser so it can access ProofChecker
- Reject unsigned JSON-LD VPs (no proof member) with clear error
- Reject JSON-LD VPs with proof member as unverifiable (ErrorInvalidProof)
  until full LD-proof verification is implemented in later steps
- Verify JWT VCs embedded in JSON-LD VPs via existing JWTProofChecker
- Reject JSON-LD status list credentials in parseStatusListCredentialBody
  with warning log and error, preventing MITM attacks on status-list resolution
- Add comprehensive table-driven tests for all rejection paths
- Update openapi integration tests for new JSON-LD rejection behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#2) from ticket-54/step-1 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/2
Reviewed-by: wistefan <wistefan@dev-env.local>
Add deprecation warnings for 'combined' and 'jsonLd' validation modes
which claim to perform JSON-LD validation but only check field presence.
Update README documentation to honestly describe each mode's behavior.

- Add DeprecatedValidationModes set and WarnDeprecatedMode() function
- Wire deprecation warning into verifier initialization
- Document actual behavior of each mode in code comments and README
- Add logging.SetTestLogger() helper for test log capture
- Add table-driven tests verifying warning for deprecated modes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#3) from ticket-54/step-2 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/3
Reviewed-by: wistefan <wistefan@dev-env.local>
… (Step 3)

Move CachingDocumentLoader from verifier/caching_client.go to
common/caching_document_loader.go so it is accessible to both
verifier/ and tir/ packages. Add configurable TTL parameters
(cacheTTL, cacheCleanup) with documented defaults.

Wire the caching document loader into tir/tokenProvider.go so
the M2M signing hot path reuses cached @context documents instead
of creating a new DefaultDocumentLoader on every call. The loader
is injected via a new documentLoader field on M2MTokenProvider.

Delete verifier/caching_client.go (code moved, not duplicated).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#4) from ticket-54/step-3 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/4
Reviewed-by: wistefan <wistefan@dev-env.local>
Add proof-carrying fields to Credential and Presentation so JSON-LD
credentials and presentations can carry their proofs through the parsing
pipeline. Extend LDProof with all Data Integrity spec fields and add
ParseLDProof/ParseLDProofs functions for structured proof extraction.

Key changes:
- LDProof: add ProofPurpose, Challenge, Domain, ProofValue, Cryptosuite
- ParseLDProof/ParseLDProofs: extract proofs from JSON maps/arrays
- Credential: add proofs field with Proofs()/SetProofs() accessors
- Presentation: change Proof *LDProof to Proofs []*LDProof slice
- AddLinkedDataProof: append to slice instead of overwriting
- MarshalJSON: serialize single proof as object, multiple as array
- parseJSONLDCredential: populate credential proofs from VC map
- parseJSONLDPresentation: parse proofs before fail-closed rejection
- Comprehensive tests for all new functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#5) from ticket-54/step-4 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/5
Reviewed-by: wistefan <wistefan@dev-env.local>
Add VerifyLinkedDataProof function that verifies JSON-LD linked data proofs
by canonicalizing the document and proof options, computing the tbs hash,
and verifying the detached JWS signature against a provided public key.

Features:
- Validates proof type (JsonWebSignature2020 only)
- Validates required fields (created, jws)
- URDNA2015 canonicalization of document and proof options
- SHA-256 hash computation matching signing order
- Detached JWS parsing with b64=false and crit=[b64] validation
- Algorithm cross-checking (RS256->RSA, ES256->EC P-256)
- Comprehensive error types for each failure mode

Tests:
- Round-trip sign+verify with RSA and EC keys
- Negative tests: tampered document, tampered timestamp, wrong key,
  algorithm mismatch, missing jws, missing created, unknown proof type,
  malformed JWS
- Table-driven parameterized test structure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#6) from ticket-54/step-5 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/6
Reviewed-by: wistefan <wistefan@dev-env.local>
- Create verifier/ld_proof_checker.go with LDProofChecker struct that
  verifies Linked Data Proofs on JSON-LD VPs and VCs using DID resolution
  and common.VerifyLinkedDataProof.
- Factor out shared DID-to-key resolution into ResolveKeyFromDID in
  verifier/key_resolver.go, used by both JWTProofChecker and LDProofChecker.
- Add ExtractDIDAndFragment and IsDidElsi helpers in key_resolver.go.
- Explicitly reject did:elsi in LD-proof context (JAdES is JWS-based).
- Wire LDProofChecker into ConfigurablePresentationParser and update
  parseJSONLDPresentation to verify VP and VC LD proofs cryptographically.
- Initialize LDProofChecker with caching document loader in InitPresentationParser.
- Add globalLDProofChecker singleton and GetLDProofChecker accessor.
- Update fail-closed logic: VPs with proofs are verified when LDProofChecker
  is available, rejected when it is not (preserving Step 1 behavior).
- Add comprehensive tests in ld_proof_checker_test.go and
  presentation_parser_test.go covering valid/invalid proofs, tampered
  documents, unresolvable DIDs, did:elsi rejection, empty proof arrays,
  and unsigned VPs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#7) from ticket-54/step-6 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/7
Reviewed-by: wistefan <wistefan@dev-env.local>
- Add VerifyLDVPProofBinding function for challenge/domain binding
  - Challenge binding prevents replay attacks by matching session nonce
  - Domain binding validates verifier audience/client ID
- Add error types: ErrorProofChallengeMismatch, ErrorProofDomainMismatch,
  ErrorHolderBindingMissingKey
- Wire challenge/domain binding into AuthenticationResponse for JSON-LD VPs
- Update verifyVPSignatureIfRequired to handle JSON-LD VP holder binding:
  - Check LD proofs and holder key when holder binding is required
  - Return ErrorHolderBindingMissingKey when key is absent
- Add comprehensive table-driven tests for VerifyLDVPProofBinding
- Add holder key propagation test with LD-proof verification
- Add verifyVPSignatureIfRequired tests for JSON-LD VP paths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#8) from ticket-54/step-7 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/8
Reviewed-by: wistefan <wistefan@dev-env.local>
…ess, and integration tests

- Add WarnLDPVCFormat() to log info message at startup when ldp_vc format
  is configured, alerting operators that LD-proof verification is enforced.
- Add FormatLDPVC constant and hasLDPVCInScope() helper checking all
  config locations (PresentationDefinition.Format, InputDescriptor.Format,
  DCQL CredentialQuery.Format).
- Update CachingStatusListClient to accept optional LDProofChecker parameter.
- Add parseJSONLDStatusListCredential() that verifies JSON-LD status list
  credential proofs via LDProofChecker (fail-closed: reject if no checker
  or no proof).
- Add ErrorStatusListJSONLDProofMissing and ErrorStatusListJSONLDProofInvalid
  error sentinels.
- Add comprehensive integration test file (ldproof_integration_test.go):
  - End-to-end JSON-LD VP with did:web holder
  - End-to-end JSON-LD VP with did:key holder
  - Negative: unsigned JSON-LD VP rejected
  - Negative: tampered JSON-LD VP rejected
  - Status list: valid LD proof accepted
  - Status list: no proof rejected
  - Status list: invalid proof rejected
  - Status list: nil checker rejects (fail-closed)
  - Status list: empty proof array rejected
  - Status list: full Fetch path with JSON-LD proof
  - Regression: JWT VP still works
  - Regression: JWT status list still works
  - WarnLDPVCFormat and hasLDPVCInScope unit tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cverifier' (#9) from ticket-54/step-8 into ticket-54/work

Reviewed-on: http://localhost:3001/general-agent-5/VCVerifier/pulls/9
Reviewed-by: wistefan <wistefan@dev-env.local>
@github-actions

Copy link
Copy Markdown

Please apply one of the following labels to the PR: patch, minor, or major. See CONTRIBUTING.md for details.

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.

1 participant