Skip to content

chore(custodian)!: derive the rng ikm straight from HKDF - #263

Merged
samlaf merged 1 commit into
seismicfrom
sl/sei-222-rng-ikm-hkdf
Aug 21, 2026
Merged

chore(custodian)!: derive the rng ikm straight from HKDF#263
samlaf merged 1 commit into
seismicfrom
sl/sei-222-rng-ikm-hkdf

Conversation

@samlaf

@samlaf samlaf commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Part of SEI-222

get_rng_ikm derived its 64 bytes as HKDF(root_key) -> MiniSecretKey -> expand(Uniform) -> secret bytes. The schnorrkel step is a leftover of the original VRF-based RNG design: no schnorrkel cryptography is performed with the result, and every consumer already narrows it to a raw [u8; 64]. It now takes those 64 bytes from the purpose derivation itself.

This changes the rng key on every network that has a root key, and RNG-precompile outputs are consensus, so re-found any running TEE devnet across the change rather than upgrading it in place. A network with no root key runs the well-known ikm literal (#262) and never reaches this derivation; the live testnet is one of those and is unaffected.

expand_purpose is now the crate's only deriver: 32 bytes for every purpose, 64 for RngPrecompile. That retires the last schnorrkel use in production code, so the crate drops the dependency and schnorrkel stays only as seismic-crypto's dev-dependency, without the serde feature nothing asked for.

The derivation also stops being public API. Key, KeyPurpose and derive_purpose_key leave the crate's surface, which is now exactly one way out per defined key: get_tx_io_sk, get_tx_io_pk, get_rng_ikm and get_snapshot_key hand a caller its key in that key's own type, and write_luks_keyfile exports the LUKS pair, whose bytes no in-process caller ever holds. Nothing outside the crate imported the removed items.

Two things fall out of that:

  • Key had one job left, scrubbing root_key, and that needs no named type: Custodian derives ZeroizeOnDrop over a plain [u8; 32]. The vacuous Result on derive_purpose_key, its .expect at three call sites, and get_snapshot_key's length try_into go with it.
  • write_luks_keyfile assembles both LUKS keys into one buffer that leaves as a file. The buffer is now Zeroizing, so the copy this process keeps is scrubbed once the write lands.

Part of SEI-222

get_rng_ikm derived its 64 bytes as HKDF(root_key) -> MiniSecretKey ->
expand(Uniform) -> secret bytes. The schnorrkel step is a leftover of
the original VRF-based RNG design: no schnorrkel cryptography is
performed with the result, and every consumer already narrows it to a
raw [u8; 64]. It now takes those 64 bytes from the purpose derivation
itself.

This changes the rng key on every network that has a root key, and
RNG-precompile outputs are consensus, so re-found any running TEE
devnet across the change rather than upgrading it in place. A network
with no root key runs the well-known ikm literal (#262) and never
reaches this derivation; the live testnet is one of those and is
unaffected.

expand_purpose<const N> is now the crate's only deriver: 32 bytes for
every purpose, 64 for RngPrecompile. That retires the last schnorrkel
use in production code, so the crate drops the dependency and
schnorrkel stays only as seismic-crypto's dev-dependency, without the
serde feature nothing asked for.

The derivation also stops being public API. Key, KeyPurpose and
derive_purpose_key leave the crate's surface, which is now exactly one
way out per defined key: get_tx_io_sk, get_tx_io_pk, get_rng_ikm and
get_snapshot_key hand a caller its key in that key's own type, and
write_luks_keyfile exports the LUKS pair, whose bytes no in-process
caller ever holds. Nothing outside the crate imported the removed
items.

Two things fall out of that:

- Key had one job left, scrubbing root_key, and that needs no named
type: Custodian derives ZeroizeOnDrop over a plain [u8; 32]. The
vacuous Result on derive_purpose_key, its .expect at three call sites,
and get_snapshot_key's length try_into go with it.
- write_luks_keyfile assembles both LUKS keys into one buffer that
leaves as a file. The buffer is now Zeroizing, so the copy this process
keeps is scrubbed once the write lands.
@samlaf
samlaf requested a review from cdrappi as a code owner August 21, 2026 15:09
@linear-code

linear-code Bot commented Aug 21, 2026

Copy link
Copy Markdown

SEI-222

@samlaf
samlaf merged commit 057b9af into seismic Aug 21, 2026
5 checks passed
@samlaf
samlaf deleted the sl/sei-222-rng-ikm-hkdf branch August 21, 2026 15:18
samlaf added a commit to SeismicSystems/seismic-evm that referenced this pull request Aug 21, 2026
Part of SEI-222
Related to SeismicSystems/enclave#263

The custodian derives the RNG precompile's ikm as 64 bytes straight out
of the root-key HKDF, and the well-known bundle carries a raw literal.
Nothing on either path imposes a keypair structure on the bytes, and the
precompile reads them as HKDF input only, so the doc comment says what
the field is rather than how one producer once shaped it.
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