Skip to content

Add an external-signer path for third-party blocks (HSM/TPM/Secure Enclave support) - #338

Open
echo-ilabs wants to merge 1 commit into
eclipse-biscuit:mainfrom
echo-ilabs:feat/external-signer-third-party-blocks
Open

Add an external-signer path for third-party blocks (HSM/TPM/Secure Enclave support)#338
echo-ilabs wants to merge 1 commit into
eclipse-biscuit:mainfrom
echo-ilabs:feat/external-signer-third-party-blocks

Conversation

@echo-ilabs

@echo-ilabs echo-ilabs commented Jul 21, 2026

Copy link
Copy Markdown

Closes #339.

create_block takes the signer's raw &PrivateKey, which rules out keys held in HSMs, TPMs and secure enclaves: they will sign bytes for you, but never release the key. This splits the operation in two, additively:

let unsigned = biscuit.third_party_request()?.prepare_block(block_builder)?;
let sig: Vec<u8> = hardware.sign(unsigned.bytes_to_sign());   // key never leaves the module
let block = unsigned.with_external_signature(public_key, &sig)?;
biscuit.append_third_party(public_key, block)?;
  • prepare_block does everything create_block did up to the signature and exposes the exact bytes to sign.
  • with_external_signature assembles the block, verifying the signature against the supplied public key up front -- so a wrong key or a corrupted signature fails right there instead of later, as an opaque deserialization error on the recipient's side.
  • create_block is now built on top of the split path, so the two stay equivalent by construction.

No wire-format or verification changes. Tests cover external-signing round trips for Ed25519 and P-256 (the algorithm hardware modules typically hold, verified by full re-deserialization), byte-for-byte equivalence of the two paths for deterministic Ed25519, and tamper/wrong-key rejection at assembly.

create_block requires the raw PrivateKey, which rules out keys held in
HSMs, TPMs and secure enclaves: they will sign bytes for you, but never
release the key.

Split the operation in two: prepare_block returns the exact bytes to
sign, and with_external_signature assembles the block from a signature
produced wherever the key lives, verifying it up front so mistakes fail
at assembly rather than at token deserialization. create_block is now
built on top of the split path, so the two stay equivalent by
construction.
@echo-ilabs
echo-ilabs force-pushed the feat/external-signer-third-party-blocks branch from 81a20c4 to b47b01d Compare July 21, 2026 16:22
@divarvel

Copy link
Copy Markdown
Contributor

Hi, this is one of the goals of #334 which should be merged soon.

Can you have a look at it and check if that matches your use-case?

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.

Third-party blocks cannot be signed by hardware-held keys

2 participants