Skip to content

feat(sdk): add opt-in hexless policy binding - #421

Draft
pflynn-virtru wants to merge 1 commit into
mainfrom
optin/hexless-policy-binding
Draft

pflynn-virtru wants to merge 1 commit into
mainfrom
optin/hexless-policy-binding

Conversation

@pflynn-virtru

@pflynn-virtru pflynn-virtru commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds an opt-in hexless policy binding: each key access object's policy binding hash is written as Base64(HMAC), the form the TDF spec defines, instead of the legacy Base64(hex(HMAC)). Default output is unchanged. Mirrors opentdf/platform#4232 (Go).

  • Config.withHexlessPolicyBinding() and the cmdline flag --hexless-policy-binding.
  • A pre-4.3.0 Config.withTargetMode overrides the opt-in and keeps the legacy form, whatever the option order.
  • Reader: when a binding decodes to 32 bytes, the rewrap request carries a copy of the key access object with the binding re-encoded as Base64(hex(HMAC)). Both forms carry the same HMAC, and every KAS verifies the legacy form, so this SDK can decrypt hexless TDFs against any KAS. Legacy bindings pass through unchanged, and the manifest itself is never modified. Older readers forward the binding unchanged and need a KAS with fix(kas): accept spec-compliant policy bindings platform#4223.
  • Known-answer vectors are shared with the Go SDK.

Part of opentdf/platform#3578.

Testing

  • mvn -pl sdk,cmdline -am test: sdk 315, sdk-pqc-bc 28, cmdline 14, all passing.
  • New tests: PolicyBindingTest (known answers for both forms; re-encode only for 32-byte bindings; null and bare-string handling), TDFTest.hexlessPolicyBindingOnEveryKeyAccess (two-KAS split), TDFTest.legacyTargetModeOverridesHexlessPolicyBinding (both orders), TDFTest.rewrapRequestCarriesLegacyBinding, ConfigTest, CommandTest.encrypt_hexlessPolicyBindingFlag_acceptedByPicocli.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an option to enable hexless policy bindings when encrypting.
    • Added SDK configuration support for selecting hexless policy-binding hashes.
    • Added compatibility handling for older target versions and key-access services.
  • Bug Fixes

    • Ensured rewrap and decryption workflows remain compatible with legacy policy-binding formats.
  • Tests

    • Added coverage for hexless and legacy policy-binding formats, target-version behavior, and command-line validation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Paul Flynn <pflynn-virtru@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f981e3bb-ba1d-40b1-a16e-583f6e63ae71
📥 Commits

Reviewing files that changed from the base of the PR and between 8fc820c and 5539e26.

📒 Files selected for processing: 7
  • cmdline/src/main/java/io/opentdf/platform/Command.java
  • cmdline/src/test/java/io/opentdf/platform/CommandTest.java
  • sdk/src/main/java/io/opentdf/platform/sdk/Config.java
  • sdk/src/main/java/io/opentdf/platform/sdk/TDF.java
  • sdk/src/test/java/io/opentdf/platform/sdk/ConfigTest.java
  • sdk/src/test/java/io/opentdf/platform/sdk/PolicyBindingTest.java
  • sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

The change adds an opt-in hexless policy-binding setting to the SDK and encrypt command. TDF creation can use raw-HMAC Base64 bindings. TDF loading converts eligible bindings for legacy KAS compatibility.

Changes: Policy-Binding Encoding

Layer / File(s) Summary
Configuration and CLI option
sdk/src/main/java/io/opentdf/platform/sdk/Config.java, cmdline/src/main/java/io/opentdf/platform/Command.java, sdk/src/test/java/io/opentdf/platform/sdk/ConfigTest.java, cmdline/src/test/java/io/opentdf/platform/CommandTest.java
TDFConfig adds hexlessPolicyBinding, defaulting to false, and withHexlessPolicyBinding() enables it. The encrypt command adds --hexless-policy-binding and applies the configuration option when set. Tests cover configuration and CLI parsing.
Binding generation
sdk/src/main/java/io/opentdf/platform/sdk/TDF.java, sdk/src/test/java/io/opentdf/platform/sdk/PolicyBindingTest.java, sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
TDF creation can use raw-HMAC Base64 bindings when enabled and when root and segment hashes are not hex-encoded. Tests cover hash formats, multiple KAS splits, and the legacy encoding selected for target mode 4.2.2.
KAS legacy compatibility
sdk/src/main/java/io/opentdf/platform/sdk/TDF.java, sdk/src/test/java/io/opentdf/platform/sdk/TDFTest.java
TDF loading passes a compatibility-transformed key-access object to KAS when conversion is needed. The rewrap test checks that the manifest retains its 32-byte binding while KAS receives the legacy 64-byte hexadecimal form.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Suggested reviewers: dmihalcik-virtru

Merge Risk: ⚪ Minimal · up to 5539e

The opt-in binding path has no identified issue that should delay merge.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 20.83% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 24 functions across 7 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: adding opt-in hexless policy binding to the SDK.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • 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

A rabbit checks the binding bytes,
Then hops through hashes, neat and light.
Raw HMAC rests in Base64,
Old KAS gets its form just right.
The manifest stays as it began,
And carrots mark the testing plan.

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

@pflynn-virtru

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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