Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
resolver = "3"
members = [
"frost-core",
"frost-hd",
"frost-ed448",
"frost-ed25519",
"frost-p256",
Expand Down Expand Up @@ -45,6 +46,7 @@ document-features = "0.2.12"
ed448-goldilocks = { version = "0.14.0-pre.15", default-features = false }
ed25519-dalek = "3.0"
hex = { package = "const-hex", version = "1.19", default-features = false, features = ["alloc"] }
hmac = { version = "0.13", default-features = false }
insta = { version = "1.48", features = ["yaml"] }
k256 = { version = "0.14", default-features = false, features = ["hash2curve"] }
p256 = { version = "0.14", default-features = false, features = ["hash2curve"] }
Expand All @@ -67,6 +69,7 @@ visibility = "0.1"
zeroize = { version = "1.9", default-features = false, features = ["derive", "alloc"] }

frost-core = { version = "3.0.0", path = "frost-core", default-features = false }
frost-hd = { version = "0.1.0", path = "frost-hd", default-features = false }
frost-ed448 = { version = "3.0.0", path = "frost-ed448", default-features = false }
frost-ed25519 = { version = "3.0.0", path = "frost-ed25519", default-features = false }
frost-p256 = { version = "3.0.0", path = "frost-p256", default-features = false }
Expand Down
10 changes: 10 additions & 0 deletions frost-hd/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Changelog

## Unreleased

- Add an experimental ciphersuite-agnostic non-hardened FROST key-family
derivation API.
- Add canonical typed paths and explicit hardened-path rejection.
- Add non-signable root wrappers and child public/private package agreement
checks.
- Document the parent-share recovery and cross-path compromise model.
31 changes: 31 additions & 0 deletions frost-hd/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "frost-hd"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
description = "Experimental blockchain-agnostic non-hardened hierarchical key derivation for FROST"
documentation = "https://docs.rs/frost-hd"
readme = "README.md"
homepage.workspace = true
repository.workspace = true
license.workspace = true
keywords = ["cryptography", "threshold", "frost", "derivation", "wallet"]
categories.workspace = true
publish = false

[dependencies]
frost-core = { workspace = true, features = ["internals"] }
hmac.workspace = true
sha2.workspace = true

[dev-dependencies]
frost-ed25519.workspace = true
hex.workspace = true
frost-ristretto255.workspace = true
frost-secp256k1.workspace = true
rand_chacha.workspace = true
rand_core.workspace = true

[features]
default = []
25 changes: 25 additions & 0 deletions frost-hd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frost-hd

Experimental, blockchain-agnostic, **non-hardened** hierarchical key
derivation for FROST key packages.

The crate is generic over a FROST ciphersuite `C` and an explicitly reviewed
`DerivationProfile<C>`. It does not provide blanket support for every
ciphersuite.

The core transformation is:

```text
s_i' = s_i + t
Y_i' = Y_i + tG
Y' = Y + tG
```

A descendant signing share plus public derivation metadata reveals the
corresponding ancestor share. See `../docs/SECURITY.md` before evaluating this
API.

This crate is research code for private review. It is not audited or
production-ready. It intentionally excludes BIP32 xpubs, Taproot wallet
policy, Solana addresses, SLIP-0010 compatibility, and hardened threshold
derivation.
69 changes: 69 additions & 0 deletions frost-hd/docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Contribution architecture

## Recommended boundary

The proposal is split into three layers.

### 1. Generic `frost-hd` protocol

This layer owns only:

- canonical, typed derivation paths;
- application/network/purpose domain separation;
- deterministic edge KDF and retry rules;
- additive transformation of `KeyPackage` and `PublicKeyPackage`;
- non-signable root wrappers;
- security documentation and vectors.

It is generic over `C: frost_core::Ciphersuite` and an explicit
`P: DerivationProfile<C>`. There is no blanket profile for all ciphersuites.
This prevents the crate from silently claiming compatibility with suites whose
key normalization or signing semantics are not linear under persistent tweaks.

The implementation follows the existing `frost-rerandomized` precedent by
using `frost-core/internals`. No raw secret scalar is exposed through the
public API.

### 2. Reviewed ciphersuite profile

A profile defines:

```text
P.ID
P.hash_to_scalar(input) -> Scalar<C>
```

The profile ID is included in every context and edge transcript. Changing the
profile ID or mapping creates a different key family.

The research tests use domain-separated `C::H1` profiles for Ed25519,
Ristretto255, and ordinary secp256k1. These are explicit test profiles, not a
blanket production claim. Maintainers should decide whether reviewed profiles
use:

1. a dedicated `HHD` ciphersuite function;
2. a standard ciphersuite-specific hash-to-field mapping;
3. domain-separated `C::H1` after cryptographic review.

An x-only Taproot profile requires separate treatment of normalization and
tweak ordering. It is deliberately not instantiated by the generic tests.

### 3. Blockchain and application adapters

Solana adapters may Base58-encode a derived Ed25519 joint public key. They must
not claim SLIP-0010 compatibility.

Bitcoin adapters may define BIP32 xpub fields, BIP340 parity normalization,
BIP341 Taproot tweak ordering, descriptors, and BIP32 conformance vectors.
Those rules remain outside the generic protocol.

Application path allocation, backups, scanning, high-water marks, and policy
are also outside `frost-hd`.

## Why not put everything in `frost-core`

Persistent wallet derivation is a broader protocol than FROST signing. A
separate crate limits the API and misuse surface while reusing existing package
abstractions. A minimal core primitive remains an alternative if maintainers
want additive package tweaking shared by `frost-rerandomized`, Taproot, and HD
derivation.
26 changes: 26 additions & 0 deletions frost-hd/docs/ATTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Prior art and attribution

This proposal builds on and must preserve attribution to:

- Zcash Foundation FROST Discussion #636, "BIP32 Derivation of FROST Keys":
https://github.com/ZcashFoundation/frost/discussions/636
- MatthewLM's observation that signing shares, verification shares, and the
joint key can receive the same additive tweak;
- Conduition's analysis and historical `taproot-bip32` prototype:
https://github.com/conduition/frost/tree/taproot-bip32
- Jesse Posner's discussion of fixed/synthetic chain-code profiles and
MuSig2-related work;
- PR #584 and successor PR #730 for the Taproot ciphersuite context:
https://github.com/ZcashFoundation/frost/pull/584
https://github.com/ZcashFoundation/frost/pull/730
- BIP32's non-hardened derivation and parent-key-recovery warning:
https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
- BIP328 synthetic xpub work for aggregate keys:
https://github.com/bitcoin/bips/blob/master/bip-0328.mediawiki
- threshold-HD research including ePrint 2023/312 and 2023/714:
https://eprint.iacr.org/2023/312
https://eprint.iacr.org/2023/714

The historical prototype is treated as useful prior art but is not rebased
wholesale because it is Taproot/BIP32-specific and diverged from the current
FROST v3 architecture.
17 changes: 17 additions & 0 deletions frost-hd/docs/BITCOIN_PROFILE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Bitcoin / secp256k1 profile

The generic protocol can derive ordinary FROST secp256k1 key packages through
an explicitly reviewed secp256k1 `DerivationProfile`. This does not embed
Bitcoin wallet policy and is not BIP32 compatibility by itself.

Exact Bitcoin interoperability requires a separate adapter defining:

- BIP32 non-hardened CKD and chain-code semantics, when exact compatibility is
a goal;
- xpub depth, parent fingerprint, child number, and version bytes;
- BIP340 x-only parity normalization;
- ordering relative to the BIP341 Taproot tweak;
- descriptor serialization and conformance vectors.

The current generic crate does not instantiate `frost-secp256k1-tr`. X-only
normalization and Taproot tweak ordering require their own profile and proof.
28 changes: 28 additions & 0 deletions frost-hd/docs/INVISIBLE_PROFILE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Invisible profile: separate from the generic protocol

Invisible uses FROST Ed25519 on Solana. Its application profile would set, for example:

```text
application = "exchange.invisible"
network = "solana-mainnet"
purpose = "lp-reimbursement"
path = m/<position>/<refill-epoch>/<shard>
```

The derived Ed25519 joint public key may be Base58-encoded as a Solana address by Invisible. Base58 and Solana address handling do not belong in `frost-hd`.

## Critical 2-of-2 implication

If a TEE receives a derived client child share and knows the public cumulative tweak, it can compute the client's parent share. Combined with the TEE side of the 2-of-2 family, this gives the TEE control of the entire bounded family. The construction therefore reduces DKG operations but does not preserve child-level cryptographic separation after delegation.

## Pilot constraints

- no global protocol root;
- one root per bounded refill batch or short operational epoch;
- root never funded;
- initially 16 children, hard cap 32;
- atomic range reservation and sealed high-water mark;
- tombstone abandoned indices; no path reuse;
- rotate through a fresh independent DKG;
- keep independent-DKG fallback;
- do not deploy in V0 without a cryptographic review and end-to-end sealed-state tests.
Loading