Skip to content

chore(deps): update every dependency to latest stable incl. DataProofs 2.0.0 (#20), v1.2.0 - #21

Merged
moisesja merged 10 commits into
mainfrom
fix/dataproofs-1.3.0-issue-20
Nov 3, 2026
Merged

moisesja merged 10 commits into
mainfrom
fix/dataproofs-1.3.0-issue-20

Conversation

@moisesja

@moisesja moisesja commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

Closes #20.

Summary

This PR started as the rebuild against DataProofs 1.3.0 that fixes #20's MissingMethodException. It now moves every dependency to its latest stable release, including DataProofs 2.0.0 (a major upstream release), so Credentials is built against exactly the graph the rest of the stack resolves: DataProofs 2.0.0, NetDid 4.0.0, NetCrypto 1.7.1, Microsoft.Extensions 10.0.14, JsonSchema.Net 9.6.0. FluentAssertions is the one deliberate hold-back (licence). Owner decision: nothing issued by an earlier Credentials exists in the wild, so there are no compatibility shims or migration steps where DataProofs 2.0.0 changes signed bytes or proof formats.

The #20 bug

Credentials.* 1.1.1 was compiled against DataProofsDotnet.Jose 1.1.0. Jose 1.3.0 replaced JwsSigner..ctor(ISigner, string) with ..ctor(ISigner, string, JwsKidPlacement): source-compatible, binary-breaking. Any app resolving a newer Jose (every app on DidComm.Core ≥ 1.4.1) threw MissingMethodException on all four JOSE signing paths. Rebuilding fixes it; a regression test pins that every emitted token keeps its kid in the protected header.

Dependencies

Package From To
DataProofsDotnet.* (Core/Jose/Cose/Rdfc/DI) 1.1.0 2.0.0
NetDid.Core / .Method.Key / .Extensions.DependencyInjection 2.3.0 4.0.0
NetCrypto 1.2.0 1.7.1
JsonSchema.Net 7.3.2 9.6.0 (API break, ported)
Microsoft.Extensions.*, System.Reflection.MetadataLoadContext 10.0.8 10.0.14
Microsoft.SourceLink.GitHub 10.0.300 10.0.403 (GHSA-23fw-v26w-5fgq; NU1902 broke CI on main)
PublicApiAnalyzers / Test.Sdk / xunit.runner.visualstudio / NSubstitute / coverlet / SkippableFact / ApiCompat tool various latest
AngleSharp pin 1.5.2 removed (DataProofsDotnet.Rdfc itself requires the patched ≥ 1.6.0)
FluentAssertions 7.0.0 held

What DataProofs 2.0.0 changes here (commit 460c675)

  • RDFC signs @direction (our dataproofs-dotnet#40, implemented upstream with rdfDirection: i18n-datatype, the reference implementations' representation). This reverses the scope decision from 17fbc44: direction-bearing credentials issue and verify under RDFC, and flipping or dropping the direction after signing fails with PROOF_VERIFICATION_ERROR. Tests cover the four W3C positions under RDFC and JCS; a number with @direction is still refused as data loss.
  • W3C gate: known failures 5 → 1 (relatedResource digest), floor 54 → 58. docs/conformance.md says 58/59. The parser test now shows the old direction messages as unknown failures, which is what the gate reports for a regression.
  • bbs-2023 follows the reference algorithms. Two refusals surfaced by the suite: a reveal that discloses no non-mandatory claim (a NetCrypto BBS-provider limit) and a reveal pointer that matches nothing (1.5.0 ignored it; 2.0.0 refuses it like the reference). Bbs2023Deriver now carries the substrate's cause in its CredentialFormatException message; IBbsDeriver documents both; two tests pin them.
  • Inherited security fix GHSA-6fxh-mc39-94vc: proof members a verifier acts on (proofPurpose, challenge, domain, expires, …) are bound to the signature under RDFC and bbs-2023. Also inherited: RDFC canonicalization hardening (hostile blank-node graphs no longer overflow the stack) and corrected canonical bytes for tied-blank-node documents.
  • The RDFC suite constructors changed shape (binary break), so this release is rebuilt; new X() binds unchanged. No Credentials public API change.

Earlier code changes in this PR

  • JsonSchema2020Validator ported to JsonSchema.Net 9 with fresh local schema and dialect registries per validation and a fetch that refuses, so one credential's schema can never answer another's $ref or redefine a dialect, and no external reference is ever fetched; Validate still never throws. 20 tests pin it, each mutation-checked.
  • Issuance exception contract: DataProofs' ProofGenerationException is rethrown as the documented InvalidOperationException, with the substrate's specific cause in the message.
  • DATA_LOSS_DETECTION_ERROR gets a verifier message; the RDFC sample lists credentials/undefined-terms/v2.
  • ES256K high-S twins (NetCrypto ≥ 1.5.0) pinned, with the freshness invariants asserted after an Accepted-with-matching-nonce control.

Verification (head 460c675)

  • -warnaserror build: 0 warnings / 0 errors. 428 tests pass.
  • 0 vulnerable packages across 29 projects; default (Core + DI) closure Newtonsoft-free; ApiCompat against 1.1.1: no breaking changes for all three packages.
  • Consumer check: a scratch app referencing DidComm.Core 1.5.0 and the packed 1.2.0 runs all 14 samples with DataProofs 2.0.0, NetCrypto 1.7.1 and NetDid 4.0.0 loaded. (Note: DidComm 1.5.0 is compiled against Jose 1.5.0; Jose's public API is unchanged in 2.0.0. The harness loads DidComm but does not exercise its own signing paths.)
  • Adversarial review of the 2.0.0 behaviours (direction binding, proof-member binding through our DI path, bbs derive/verify, exception contract, JsonSchema.Net 9.6.0): result posted in the thread.
  • W3C conformance: runs on this PR with the named-failure gate (floor 58); result posted in the thread.

Release

Hold the v1.2.0 tag until the remaining v1.2.0 work lands; the CHANGELOG heading reads "Unreleased" until then.

🤖 Generated with Claude Code

moisesja and others added 3 commits October 26, 2026 20:08
…ink 10.0.403 (#20), bump to v1.2.0

Credentials 1.1.1 was compiled against DataProofsDotnet.Jose 1.1.0. Jose 1.3.0 replaced
JwsSigner..ctor(ISigner, string) with (ISigner, string, JwsKidPlacement) - source-compatible,
binary-breaking - so every JOSE signing path (vc+jwt, SD-JWT VC, KB-JWT, vp+jwt) threw
MissingMethodException once a consumer such as DidComm.Core 1.4.1 resolved Jose 1.3.0.

- DataProofsDotnet.* 1.1.0 -> 1.3.0
- NetCrypto 1.2.0 -> 1.7.1 (DataProofs.Core 1.3.0 floors >= 1.4.0)
- Microsoft.SourceLink.GitHub 10.0.300 -> 10.0.403 (GHSA-23fw-v26w-5fgq; NU1902 broke restore)
- Remove the #18 AngleSharp pin: DataProofsDotnet.Rdfc 1.3.0 floors the patched AngleSharp >= 1.6.0
- CredentialsVersion 1.1.1 -> 1.2.0

No source or public API change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…essons

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regression guards from the issue #20 adversarial pass over DataProofs 1.3.0 / NetCrypto 1.7.1:
JSON-serialized JWS with an unsigned kid is never accepted through any entry point; compact forgeries
whose signed kid disagrees with the issuer/holder are rejected; every emitted vc+jwt / SD-JWT issuer JWT /
kb+jwt / vp+jwt keeps its kid in the protected header (JwsKidPlacement.Auto); hostile headers fail
without escaping exceptions and a bad signature is Failed, not Indeterminate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copy link
Copy Markdown
Owner Author

Review: looks sound, approve once CI is green.

I read the diff. I did not build or run anything locally. The two CI jobs (ubuntu and windows) were still in progress when I looked.

What's good

  • The change fixes the MissingMethodException from Rebuild against DataProofs 1.3.0: JOSE and SD-JWT signing throw MissingMethodException when Jose 1.3.0 is resolved (e.g. with DidComm 1.4.1) #20 the right way. It rebuilds against DataProofs 1.3.0 with no source change. It also raises the NetCrypto floor, which DataProofs.Core 1.3.0 requires, and bumps the version to 1.2.0.
  • Making this a minor release is correct. Anyone on Jose 1.2.x is forced to move, and the CHANGELOG says to stay on 1.1.1 in that case.
  • The CHANGELOG states the NetCrypto 1.5.0+ behaviour change plainly. ES256K verification now accepts high-S signatures, so signature bytes are no longer unique. The note to key replay and dedup on signed content (jti, nonce, credential id) is the right guidance.
  • Removing the AngleSharp pin is justified, because DataProofs.Rdfc 1.3.0 floors AngleSharp at ≥ 1.6.0. Credentials.Rdfc should still resolve the patched version transitively.
  • The SourceLink bump clears the NU1902 failure that was breaking CI on main.
  • Adding JoseSubstrateRegressionTests (4 tests) is the right kind of coverage. It covers an unsigned-kid JSON JWS, a signed kid that disagrees with the issuer or holder, a protected-header kid on every emitted token, and hostile protected headers. This matches the CLAUDE.md rule on testing both post-sign tampering and self-consistent forgeries.

Concerns and nits

  1. No test would have caught Rebuild against DataProofs 1.3.0: JOSE and SD-JWT signing throw MissingMethodException when Jose 1.3.0 is resolved (e.g. with DidComm 1.4.1) #20. The new tests pin JOSE behaviour, but nothing exercises binary compatibility across a consumer-resolved Jose version. This will happen again at the next DataProofs minor. A CI job that restores with a newer Jose, or a smoke test against DidComm.Core, would catch it.
  2. Unverified claims. The "all 14 samples ran on NetDid 3.1.0" and "ApiCompat passes against 1.1.1" statements are not backed by anything in the PR. Please confirm that the ApiCompat check runs in CI.
  3. Large dependency jump. NetCrypto goes from 1.2.0 to 1.7.1, which includes key-store custody changes and hardening. The "only adds APIs" claim is checked by the build only for the surface this library uses. Those APIs are not exercised for ES256K high-S, so please confirm that a test pins the new behaviour. The new tests only cover kid handling.
  4. Scope. The PR bundles a bug fix, a dependency churn, a security bump and a task record. That's acceptable here, since the pieces are interdependent and the commits are separate.

I'm not approving until the two CI jobs finish green. Items 1–3 are non-blocking.


Generated by Claude Code

…ss invariants (#20)

Addresses PR #21 review item 3. An ES256K (R, n-S) signature twin of a vc+jwt now verifies (pinned), but a
twin never defeats freshness or disclosure binding: a malleated issuer JWT inside an SD-JWT+KB presentation
breaks sd_hash, and malleated KB-JWT / vp+jwt twins still carry the nonce / challenge they signed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@moisesja

Copy link
Copy Markdown
Owner Author

Thanks for the review. Taking the items in order:

1. No test would have caught #20. Agreed. Nothing inside the repo can catch it, because every in-repo build compiles against the pinned DataProofs. DataProofs' 1.3.0 changelog also says binary compatibility across minor versions is out of scope for it, so this will recur. The guard has to run outside the pinned graph. Two options: a scheduled latest-dependencies job that floats DataProofs, NetCrypto and NetDid, or a consumer smoke test that references DidComm.Core alongside the freshly packed Credentials. Either needs its own design (floating CPM versions vs. a consumer-app harness). The task record lists it as a proposed follow-up, and it is not part of this PR.

2. Unverified claims.

  • ApiCompat runs in CI. The API compatibility (semver) job in .github/workflows/ci.yml runs tools/check-api-compat.sh. That script compares each packed library against its latest published nuget.org version, 1.1.1 here. It passed on this PR. Locally it reported APICompat ran successfully without finding any breaking changes for Core, DI and Rdfc.
  • Consumer check. This was run locally, outside the repo, with an isolated NUGET_PACKAGES so the local 1.2.0 never reached the global cache. A scratch console app referenced DidComm.Core 1.4.1 and the packed Credentials.* 1.2.0 (Core, DI and Rdfc) and ran all 14 repo samples through their RunAsync:
    DidComm.Core loaded: 1.4.1.0
    14/14 samples passed   (Bbs2023, CoseEnvelope, DataIntegrity, DataIntegrityRdfc, FullPipeline, IssuerTrust,
                            JoseEnvelope, PresentationDataIntegrity, PresentationJose, Schema, SdJwtPresentation,
                            SdJwtVc, StatusList, Vcdm11)
      loaded Credentials.Core: 1.2.0+0aca7c1…
      loaded DataProofsDotnet.Jose: 1.3.0+377cb8e…
      loaded NetCrypto: 1.7.1+b38a6c1…
      loaded NetDid.Core: 3.1.0+ecddbfe…
      loaded NetDid.Method.Key: 2.3.0  /  NetDid.Extensions.DependencyInjection: 2.3.0
    
    The same app against the published 1.1.1 passed 10/14. JoseEnvelope, PresentationJose, SdJwtPresentation and SdJwtVc failed with MissingMethodException: … JwsSigner..ctor(NetCrypto.ISigner, System.String). Making this harness repeatable is the follow-up in item 1.

3. ES256K high-S is not pinned. Fair. It was covered only by an uncommitted adversarial probe. Commit fa4c3e4 adds Es256k_signature_twins_verify_but_never_defeat_freshness_or_disclosure_binding to JoseSubstrateRegressionTests. It pins both the behaviour change and the invariants that keep the change harmless:

  • An ES256K (R, n−S) twin of a vc+jwt verifies.
  • Replacing the issuer JWT's signature inside an SD-JWT+KB presentation breaks sd_hash → Rejected.
  • A KB-JWT twin checked against a fresh nonce → Rejected.
  • A vp+jwt twin checked against a fresh challenge → Rejected.

On the wider NetCrypto 1.4.0 → 1.7.1 jump: its changelog lists only additive custody APIs, key-store hardening, and this one verify-side change. The full suite (now 396 tests) runs with NetCrypto 1.7.1 loaded.

4. Scope. Agreed. The pieces depend on each other, and the commits are separate.

🤖 Generated with Claude Code

moisesja and others added 3 commits October 29, 2026 21:29
The first-party stack moved together (DataProofs 1.5.0, NetDid 4.0.0, DidComm.Core 1.5.0). This brings
Credentials onto exactly that graph:

- DataProofsDotnet.* 1.3.0 -> 1.5.0, NetDid.* 2.3.0 -> 4.0.0, JsonSchema.Net 7.3.2 -> 9.5.0
- Microsoft.Extensions.* / MetadataLoadContext 10.0.8 -> 10.0.14 (NetDid 4.0.0 floors 10.0.14)
- PublicApiAnalyzers 5.6.0, Test.Sdk 18.11.0, xunit.runner.visualstudio 4.0.1, NSubstitute 6.2.0,
  coverlet 10.1.0, SkippableFact 1.5.85, ApiCompat tool 10.0.403
- FluentAssertions deliberately held at 7.0.0 (last Apache-2.0 release)

Code changes the upgrade requires:
- JsonSchema2020Validator ported to JsonSchema.Net 9. Each validation builds into a fresh local
  SchemaRegistry: v9 otherwise registers schemas process-wide, so one credential's schema could answer
  another's $ref, and a reused $id would throw. JsonSchemaException (v9's error for structurally invalid
  schemas) is caught, so the validator still never throws. New tests pin isolation, $id reuse,
  malformed schemas, external $ref and the ReDoS cut-off.
- DataIntegrityMechanism wraps DataProofs' ProofGenerationException (thrown since 1.4.0) in the
  InvalidOperationException IIssuer/IHolder document, keeping the substrate type behind the seam.
- DATA_LOSS_DETECTION_ERROR (DataProofs 1.5.0 RDFC data-loss fix) gets a verifier message.
- The RDFC sample lists credentials/undefined-terms/v2 so its custom claims are signable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion; never throw (#20)

Found by the adversarial pass on the JsonSchema.Net 9 port (e12819c), before release:

- Dialect-registry poisoning. JsonSchema.Net 9 records document-defined $schema dialects in the
  process-wide DialectRegistry.Global, first writer wins. A schema supplied with one credential could
  redefine a custom dialect as core-only (validation keywords become annotations), flipping a later
  credential that declares it from Rejected to Accepted. The unsynchronized dictionary also grew without
  bound and corrupted under concurrency. Each validation now builds into a fresh local DialectRegistry.
- Fetch fallback. JsonSchema.Net falls back to SchemaRegistry.Global.Fetch, which any code in the host
  process may set. The local registry's Fetch now refuses, so no external reference is ever fetched.
- Exceptions escaping Validate. A non-string $schema or a lone surrogate in a keyword value threw
  InvalidOperationException (v7 returned Indeterminate). The build step now maps every
  non-cancellation exception to Indeterminate schema.unparseable.

Each fix is pinned by tests and mutation-checked (removing it fails the tests). The false comment that
the dialect was fixed at 2020-12 is corrected: a declared $schema selects a known or same-document
dialect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ord, lessons

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@moisesja moisesja changed the title fix(deps): rebuild against DataProofs 1.3.0 / NetCrypto 1.7.1 (#20), v1.2.0 chore(deps): update every dependency to latest stable (#20), v1.2.0 Oct 30, 2026
@moisesja

Copy link
Copy Markdown
Owner Author

Not ready to merge: the conformance gate is failing on the reviewed head 2335ef7.

I reviewed the title, description, all changed files and commit messages, and ran dotnet test Credentials.sln --no-restore --verbosity minimal: 418 passed, 1 W3C test skipped locally. GitHub's ordinary CI, API compatibility, API coverage and consumer-closure jobs passed. The separate W3C job failed: 54 passing, 5 failing, against the required baseline of 57.

Blocking — resolve the RDFC language-direction compatibility loss introduced by Directory.Packages.props:23. Four failing cases are valid language-value objects in name, description, issuer.name and issuer.description. They fail issuance with “The document or proof configuration cannot be RDFC-canonicalized without losing data.” For example, a credential containing "name":{"@value":"Example","@language":"en","@direction":"ltr"} now hits this refusal.

I reproduced the dependency difference: DataProofs.Rdfc 1.1.0 canonicalizes the example; 1.5.0 throws JsonLdDataLossException. This is intentional upstream security hardening, not a bug in this PR's exception wrapper: the old canonicalizer produced identical bytes for ltr and rtl. Do not restore that unsafe behavior by removing the guard or stripping direction.

Please resolve the intended support contract before merge. Secure RDFC direction support belongs in DataProofs; adopting the fix, regression coverage and accurate compatibility documentation belong here. If direction-bearing RDFC credentials are deliberately unsupported for this release, make that an explicit scope decision and document the exact limitation and conformance expectations. Simply lowering the passing-count threshold would hide the regression. Add focused coverage for the four affected positions and update docs/conformance.md, which still claims 57/59 and passing language-value cases, plus the release notes. The fifth failure, relatedResource digest validation, is already a documented gap; I am not attributing it to this PR.

Non-blocking test gap — JoseSubstrateRegressionTests.cs:441–452. The malleated KB-JWT and VP-JWT are only checked with the wrong nonce/challenge. First assert each same twin succeeds with matching expectations, then assert the stale case fails for the freshness reason. Otherwise a signature-verification rejection also satisfies these assertions without exercising the claimed replay defense.

The scope is broad but coherent for the requested stack upgrade, and the commit messages are specific. The previously acknowledged consumer binary-compatibility harness remains a follow-up; I am not presenting it as a newly discovered defect.

…cit v1.2.0 scope decision (#20)

Addresses the PR #21 review. DataProofs 1.5.0 refuses to RDFC-sign a language value object with
@direction (fail-closed: the Data Integrity specs define no lossless canonicalization of direction and
JSON-LD's default drops it, so earlier versions signed bytes that did not carry it). The W3C suite's
four issuer-side direction cases (name, description, issuer.name, issuer.description) therefore fail,
57 -> 54 of 59.

- Scope decision: direction-bearing credentials are unsupported under the RDFC suites in v1.2.0; the
  JCS suites are the supported path. Documented in docs/conformance.md and the CHANGELOG; tracked
  upstream as dataproofs-dotnet#40 (opt-in rdfDirection: i18n-datatype).
- Gate: W3cVcdm2SuiteTests keys on five NAMED known failures (the suite's own assertion messages) plus
  a floor of 54. A failure outside the list fails the gate however many tests pass, so a regression
  cannot hide behind the count. Fails closed if the mocha failure section cannot be parsed; prints a
  notice when a known failure starts passing. ParseFailures is pinned by unit tests on a captured
  mocha excerpt, since the suite only runs on CI.
- Focused coverage (RdfcIssueVerifyTests, 8 cases over the four positions): RDFC refuses @direction
  naming the cause; JCS secures and verifies the same document; language-only secures under RDFC;
  adding @direction after RDFC signing is Rejected with DATA_LOSS_DETECTION_ERROR.
- DataIntegrityMechanism's InvalidOperationException now includes the substrate's specific cause
  ("uses @direction") one level down, not only the generic data-loss sentence.
- JoseSubstrateRegressionTests: the KB-JWT and vp+jwt ES256K twins are first Accepted with matching
  nonce/challenge, then Rejected for freshness (holder_binding_replay for the VP; the key-binding code,
  not an issuer-signature code, for the KB-JWT).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@moisesja

Copy link
Copy Markdown
Owner Author

Addressed in 17fbc44. Point by point:

Blocking — RDFC language-direction support contract. Resolved as an explicit scope decision, not by weakening the guard or lowering a count.

  • What the contract is. Language value objects with @direction are unsupported under the RDFC suites (eddsa-rdfc-2022, ecdsa-rdfc-2019, bbs-2023) in v1.2.0. Issuance throws InvalidOperationException that now names the cause ("uses @direction"); verification of such a credential, from any issuer, fails with DATA_LOSS_DETECTION_ERROR. The supported path is the JCS suites, which sign the JSON as written, or a language value object without @direction.
  • Why it is a scope decision rather than a fix here. vc-data-integrity and vc-di-eddsa contain no occurrence of "direction" or rdfDirection: the Data Integrity specs define no lossless canonicalization of direction, and JSON-LD 1.1's default conversion drops it. That is why ≤ 1.4 signed identical bytes for ltr/rtl. A lossless mode exists (rdfDirection: i18n-datatype, implemented by dotNetRDF 3.5.1), but any implementation enabling it unilaterally produces proofs that verifiers using the JSON-LD default cannot check. So secure direction support is an upstream, interop-level decision: filed as dataproofs-dotnet#40 (an opt-in mode with the interop caveat stated; refuse-by-default stays).
  • Focused coverage for the four positions (RdfcIssueVerifyTests, two theories over name, description, issuer.name, issuer.description, 8 cases): RDFC refuses the direction-bearing value with a message naming @direction and the DataProofs exception as InnerException; the same document issues and verifies under eddsa-jcs-2022; a language-only value in the same position issues and verifies under RDFC (the limitation is direction, not language value objects); and the security meaning — issue under RDFC with language only, then add @direction after signing → Rejected with DATA_LOSS_DETECTION_ERROR, where ≤ 1.4 verified it.
  • The gate no longer hides regressions behind a count. W3cVcdm2SuiteTests now keys on five named known failures (the suite's own assertion messages: the four direction cases and relatedResource digest) and keeps 54 only as a sanity floor. A failure outside the list fails the gate however many tests pass; the run fails closed if the mocha failure section cannot be parsed; a known failure that starts passing prints a notice to remove it and raise the floor. ParseFailures is pinned by four unit tests on a captured mocha excerpt, since the suite itself only runs on CI.
  • Docs and release notes. docs/conformance.md is rewritten: 54/59, the gate design, the direction row (positions, reason, security meaning, JCS alternative, #40), a note that the later assertions in those four it blocks are no longer reached, and that the type term-resolution case (a documented gap up to v1.1.1) now passes for RDFC-secured input. The CHANGELOG states the limitation and the 57 → 54 change.
  • Verdict on 17fbc44: W3C job 40995430968 — 54 passing, 5 failing (floor 54, 5 known failures), all five matched, no unexpected failure. Ubuntu build + test passed; the Windows build, ApiCompat, API coverage and consumer-closure jobs were still running when I posted this (all passed on 2335ef7, and this commit changes tests, docs and one exception message).

Non-blocking — JoseSubstrateRegressionTests twins. Done as you described: the KB-JWT and vp+jwt ES256K twins are first asserted Accepted with the matching nonce/challenge, then Rejected with stale expectations. The stale vp+jwt asserts holder_binding_replay. For the KB-JWT, Credentials maps every KB-JWT problem to one code (sdjwt_key_binding_invalid), so the Accepted assertion is what excludes a signature rejection; the test additionally asserts that code and the absence of PROOF_VERIFICATION_ERROR (the issuer-signature code). A distinct KB-JWT freshness code would be a small follow-up if you want it.

Not changed: the shim stays on eddsa-rdfc-2022 (switching to JCS would change what the suite measures), and no @direction is stripped before signing.

🤖 Generated with Claude Code

DataProofs 2.0.0 is a major upstream release; Credentials is rebuilt against it (the RDFC suite
constructors changed shape: source-compatible, binary-breaking). No Credentials public API change.
Owner decision: nothing issued by an earlier Credentials exists in the wild, so no compatibility shims.

What 2.0.0 changes here:
- RDFC now signs a language value's @direction (dataproofs #40; rdfDirection: i18n-datatype, the
  reference implementations' representation). Last round's scope decision is reversed: the direction
  tests now assert issue+verify under RDFC and JCS, and that flipping or dropping the direction after
  signing fails with PROOF_VERIFICATION_ERROR; a number with @direction is still DATA_LOSS.
- The W3C gate drops the four direction cases from KnownFailures (1 known failure left: relatedResource
  digest), floor 54 -> 58; docs/conformance.md says 58/59. The parser test now shows the old direction
  messages as unknown failures.
- bbs-2023 follows the reference algorithms. Two new refusals surfaced by the suite: a reveal that
  discloses no non-mandatory claim (NetCrypto's BBS provider limit) and a reveal pointer that matches
  nothing (1.5.0 ignored it). Bbs2023Deriver now carries the substrate's cause in its
  CredentialFormatException message; IBbsDeriver documents both; two tests pin them; four tests reveal
  one non-mandatory claim.
- Inherited security fix GHSA-6fxh-mc39-94vc (proof members bound to the signature under RDFC/bbs) and
  the RDFC canonicalization hardening; RDFC bytes change for tied-blank-node documents. CHANGELOG states
  all of it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@moisesja moisesja self-assigned this Nov 3, 2026
@moisesja moisesja added this to the 1.2.0 milestone Nov 3, 2026
@moisesja moisesja changed the title chore(deps): update every dependency to latest stable (#20), v1.2.0 chore(deps): update every dependency to latest stable incl. DataProofs 2.0.0 (#20), v1.2.0 Nov 3, 2026
@moisesja

moisesja commented Nov 3, 2026

Copy link
Copy Markdown
Owner Author

Review of 460c675: no new blocking defect found. One non-blocking security regression coverage gap remains.

I read the title, description, diff and all nine commit messages, including the schema migration and proof/dependency changes. This is a broad upgrade (25 files), but the changes serve the same stack-convergence goal and the commit messages explain them clearly.

Missing integration coverage / missing evidence: the description says the DataProofs 2.0.0 adversarial results are “posted in the thread”; I could not find that report. The committed RDFC tests cover direction and undefined-term tampering, but do not pin the newly inherited GHSA-6fxh-mc39-94vc proof-member/context-binding fix through Credentials’ public verifier. Please link or post the promised reproducible probe and results. Preferably retain a representative regression in RdfcIssueVerifyTests (and the BBS integration tests): an honest Accepted control, then the advisory’s context-based reinterpretation of a verification-relevant proof member must produce a definitive Failed/Rejected result. Ordinary wrong-challenge tests do not exercise that attack. This is a coverage/evidence request, not a claim that DataProofs 2.0.0 is still vulnerable.

Verified: dotnet test Credentials.sln --no-restore --verbosity minimal completed with 428 passed, zero failures, one external W3C test skipped locally. CI passed on this head, including Windows, Ubuntu, API compatibility, API coverage and default dependency closure. The W3C job reports 58 passing / one documented failure, and its named-failure gate passes.

The previous blocking direction concern is resolved: all four positions now issue and verify, and flipping/removing direction is rejected. The high-S freshness tests now include the missing successful controls. The deferred relatedResource digest gap and consumer compatibility harness are already acknowledged follow-ups, not new findings.

@moisesja

moisesja commented Nov 3, 2026

Copy link
Copy Markdown
Owner Author

460c675 — DataProofs 2.0.0 folded in; all 6 checks green.

  • Build + test (Ubuntu, Windows): pass — 428 tests.
  • W3C VCDM 2.0 suite (run 41564911135): 58 passing, 1 failing (floor 58, 1 known failure). The one failure is the documented relatedResource digest case; the four language-and-direction cases pass again now that RDFC signs @direction (dataproofs-dotnet#40 landed in 2.0.0), so the scope decision from 17fbc44 is reversed and docs/conformance.md says 58/59.
  • API compatibility (semver) vs 1.1.1: no breaking changes. API coverage: pass. No-Newtonsoft consumer closure: pass.
  • Locally: 0 vulnerable packages across 29 projects; DidComm.Core 1.5.0 consumer harness runs 14/14 samples with DataProofs 2.0.0, NetCrypto 1.7.1 and NetDid 4.0.0 loaded.

The adversarial pass on the 2.0.0 behaviours (direction binding, proof-member binding, bbs-2023 derive/verify, exception contract, JsonSchema.Net 9.6.0) is still running and will be posted separately when it reports; it does not block review.

🤖 Generated with Claude Code

@moisesja
moisesja merged commit 047acf3 into main Nov 3, 2026
6 checks passed
@moisesja
moisesja deleted the fix/dataproofs-1.3.0-issue-20 branch November 3, 2026 14:01
@moisesja

moisesja commented Nov 3, 2026

Copy link
Copy Markdown
Owner Author

Adversarial pass on 460c675 (DataProofs 2.0.0 behaviours): nothing exploitable attributable to the change.

35 attacks through the public roles (IIssuer/IHolder/IVerifier/IBbsDeriver), each post-sign tampering and self-consistent forgeries:

  • RDFC @direction (i18n-datatype): flipping, removing, re-languaging or re-valuing a directional value, at the root and in credentialSubject, in multi-language arrays, under eddsa-rdfc-2022 and ecdsa-rdfc-2019 → Rejected PROOF_VERIFICATION_ERROR. A context-level default direction cannot be made to read a direction that was not signed. @direction on a number/boolean → refused at issuance, DATA_LOSS_DETECTION_ERROR at verify. Respelling as the explicit i18n#en_ltr datatype or changing language-tag case is the same RDF literal (representation only, no verdict change).
  • Proof members bound to the signature (GHSA-6fxh-mc39-94vc) through our DI path: renaming expires/challenge/domain/proofPurpose via added proof or document contexts, @reverse promotion of a nested proof node, compact-IRI verificationMethod → all Rejected, no escaped exception. RDFC-bound VPs: stale challenge → INVALID_CHALLENGE_ERROR, wrong domain → INVALID_DOMAIN_ERROR, forged holder → holder_binding. JCS suites unchanged.
  • bbs-2023: tampering revealed mandatory/selective values, re-adding withheld claims, moving claims between subjects, flipping a signed direction in a reveal, presenting a base as derived, pointers into proof/@context, 35 hostile proofValue encodings → Rejected or CredentialFormatException, never an escaped substrate exception, ≤ 47 ms each. The deriver's new message never quotes document content.
  • JsonSchema.Net 9.6.0: only FormatRegistry changed upstream (decompiled diff); registry isolation and no-fetch pins still hold (25/25).

Pre-existing hardening items surfaced along the way (identical at 17fbc44 and in 1.1.1, so not caused by this PR): claim-term respelling without context allowlisting is #22 (KnownContexts); the rest are tracked privately per SECURITY.md and will come as a follow-up. One timing probe (an 8,000-item array under RDFC, the upstream "slow expansion" limitation) did not complete.

🤖 Generated with Claude Code

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.

Rebuild against DataProofs 1.3.0: JOSE and SD-JWT signing throw MissingMethodException when Jose 1.3.0 is resolved (e.g. with DidComm 1.4.1)

1 participant