Skip to content

fix(sdk): DSPX-1561 verify assertion bindings under the assertions specification - #438

Draft
dmihalcik-virtru wants to merge 1 commit into
DSPX-1561-assertion-hashfrom
DSPX-1561-binding-verification
Draft

dmihalcik-virtru wants to merge 1 commit into
DSPX-1561-assertion-hashfrom
DSPX-1561-binding-verification

Conversation

@dmihalcik-virtru

@dmihalcik-virtru dmihalcik-virtru commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Proposed Changes

  • Each assertion is verified with exactly one key, selected once by its exact id: the per-ID key, otherwise the default key, otherwise the payload key with HS256 (ZTDF assertions specification, Section 6.1). A failure is final. An empty or unusable configured key, including PEM text given as an HS256 secret, fails with configuration-error instead of falling through to the next source.
  • The binding is verified only with that key and its algorithm. An embedded jwk or x5c must hold the same public key (RFC 7638 thumbprint), or verification fails with signer-not-permitted (Section 6.2). Embedded keys that are symmetric, private, malformed, not canonically encoded, or contradictory, and any embedded key in HMAC mode, fail with invalid-embedded-key.
  • The JWS is checked directly: compact serialization, strict base64url, no crit header, no duplicate header or claim members, and an alg equal to the selected key's. Claims other than assertionHash and assertionSig are ignored.
  • Binding forms (Section 5.1): a missing method means jws, jws and JWS are accepted, and STANAG 4778 binding objects are reported as unsupported-binding.
  • Checks follow the Section 8 order, and every failure is an SDK.AssertionFailureException with its reason. Key selection stays inside loadTDF; Manifest.Assertion.verify has no side effects.

Stacked on: #437. This supersedes the verification change in #434; it will be rebased once that and #435 land.
Split out of #432 (draft; the complete change). Cross-SDK counterparts: opentdf/platform#4307, opentdf/web-sdk#1141; cross-SDK test: opentdf/tests#706.

Compatibility:

  • An assertion signed with RS256 and read with no key configured fails with algorithm-mismatch.
  • A configured default key applies to every assertion without a per-ID key, including payload-key assertions such as system-metadata, so those fail when only a default key is set.
  • An unusable configured key is a configuration-error even if another source would have verified the assertion.

Checklist

  • I have added or updated unit tests
  • I have added or updated integration tests (if appropriate)
  • I have added or updated documentation

Testing Instructions

  • mvn -pl sdk,cmdline -am test (new cases in AssertionVerificationTest and AssertionVerifierTest).

…ecification

Each assertion is verified with exactly one key, selected once by its
exact id: the per-ID key, else the default key, else the payload key
with HS256 (spec Section 6.1). A failure is final, and an empty or
invalid configured key, including PEM text given as an HS256 secret, is
a configuration error.

Each binding is verified only with the key selected from configuration
and that key's algorithm; an embedded jwk or x5c must match it (Section
6.2). Embedded keys that are symmetric, private, malformed for their key
type, not canonically encoded, or contradictory, and any embedded key in
HMAC mode, are rejected. The JWS alg must equal the selected key's
algorithm, crit headers and duplicate JOSE members are rejected, base64
is decoded strictly, claims other than assertionHash and assertionSig
are ignored, and both binding forms of Section 5.1 are recognized, with
binding objects reported as unsupported.

Checks follow the Section 8 order, and every failure is reported as an
SDK.AssertionFailureException with its reason. JSON that does not parse
inside an assertion is reported as invalid-json. Key selection stays
inside loadTDF, and Manifest.Assertion.verify has no side effects.

Signed-off-by: Dave Mihalcik <dmihalcik@virtru.com>
@coderabbitai

coderabbitai Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

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