chore(custodian)!: derive the rng ikm straight from HKDF - #263
Merged
Conversation
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
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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: