Skip to content
Merged
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
63 changes: 63 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,69 @@

## UNRELEASED

## schnorr_fun v0.13.0

A security audit of `chilldkg` produced a batch of fixes and an API rework.
See PRs [#247](https://github.com/LLFourn/secp256kfun/pull/247) and
[#248](https://github.com/LLFourn/secp256kfun/pull/248).

Security fixes (chilldkg):

- **PoP binding**: `simplepedpop` proofs of possession now sign the slot index
and `com[0]` y-parity. Closes a cross-slot replay capability where an honest
contributor's `(com, pop)` could be replayed at any other slot, including
with the public key negated under BIP340 x-only verification.
- **Certifier signature verification**: `Certifier::receive_certificate` always
verifies the supplied signature. Previously a duplicate registration silently
swallowed an unverified second signature — for randomized/VRF schemes this
was the live path.
- **CertifiedKeygen non-serializable**: `bincode`/`serde` derives removed.
Deserialization bypassed `Certifier::finish`'s verification, allowing
attacker-chosen VRF gammas to feed `vrf_security_check`.
- **finalize rejects extras**: `SecretShareReceiver::finalize` now rejects
certificate-map entries from keys outside the expected certifying set,
preventing pollution of downstream consumers like the VRF beacon.
- **receive_secret_share validation**: missing share index and wrong-keypair
cases are returned as specific errors instead of silently surfacing as
`InvalidSecretShare`.
- **Contributor count enforcement**: every honest role commits to
`n_contributors` up-front and rejects any `AggKeygenInput` whose slot
count disagrees, closing the ghost-contributor padding rough edge.
- **DoS panic fixes**: `encpedpop::Contributor::verify_agg_input` and
`SharedKey` decoding no longer panic on adversary-supplied inputs.

API changes (chilldkg):

- `Contributor` is type-parameterized by role: `Contributor<ShareReceiver>` or
`Contributor<AuxContributor>`. Wrong-role calls become compile errors.
Unified `gen_keygen_input` constructor replaces the per-role variants.
- `verify_agg_input` is per-role. The `ShareReceiver` variant atomically pairs
the secret share with the verified aggregate. In `certpedpop` the share is
withheld in `SecretShareReceiver` until `finalize` runs with a complete
certificate map.
- Each `Contributor` now saves the receiver-encryption keys (and aux
contributor keys at the certpedpop layer) and verifies the aggregated input
against that saved view rather than trusting the coordinator. `cert_bytes()`
binds both keysets, so a malicious coordinator showing different parties
different keysets produces different `cert_bytes` per victim and mutual
certification fails.
- Receiver encryption keys leave the encpedpop wire form (they were embedded
next to each encrypted share); aux contributor keys stop being a `finalize`
parameter. Both move onto the contributor at `gen_keygen_input` time.
- `Coordinator::add_input` and `missing_from` use a `Party` enum
(`Receiver(u32) | AuxContributor(u32)`) instead of raw absolute slot indices.
- `encpedpop::AggKeygenInput` deserialization rejects mismatched lengths via a
private wire type.
- `&'static str` errors are replaced with typed enums across chilldkg; broad
errors are split into per-function variants. `EncryptionCheckError` is a
shared sub-enum between aux and share-receiver verify paths.
- The PoP message domain separator is now `"BIP DKG/pop message"`, matching
the BIP DKG draft. Wire-incompatible with older PoPs.

Other:

- Add `#[must_use]` to `HashAdd` trait methods.

## vrf_fun v0.12.1

- **SECURITY FIX**: Fix nonce reuse in RFC 9381 VRF proving. The `Rfc9381Transcript` nonce derivation did not include the transcript state (VRF input, public key, gamma), producing identical nonces across different VRF inputs with the same key. This enables full secret key recovery from any two proofs. Found by Mathias Hall-Andersen (@rot256) of zkSecurity. See [#244](https://github.com/LLFourn/secp256kfun/pull/244).
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rand_chacha = { version = "0.3", default-features = false }

# Local crates
secp256kfun = { path = "./secp256kfun", version = "0.12", default-features = false }
schnorr_fun = { path = "./schnorr_fun", version = "0.12", default-features = false }
schnorr_fun = { path = "./schnorr_fun", version = "0.13", default-features = false }
ecdsa_fun = { path = "./ecdsa_fun", version = "0.12", default-features = false }
sigma_fun = { path = "./sigma_fun", version = "0.9", default-features = false }
vrf_fun = { path = "./vrf_fun", version = "0.12", default-features = false }
2 changes: 1 addition & 1 deletion schnorr_fun/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

[package]
name = "schnorr_fun"
version = "0.12.0"
version = "0.13.0"
authors = ["LLFourn <lloyd.fourn@gmail.com>"]
edition = "2024"
rust-version = "1.85.0"
Expand Down
2 changes: 1 addition & 1 deletion schnorr_fun/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This implementation is based on the [BIP-340] specification, but is flexible eno

``` toml
[dependencies]
schnorr_fun = "0.12"
schnorr_fun = "0.13"
sha2 = "0.10"
```

Expand Down
2 changes: 1 addition & 1 deletion secp256kfun/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "secp256kfun"
version = "0.12.0"
version = "0.12.1"
authors = ["LLFourn <lloyd.fourn@gmail.com>"]
license = "0BSD"
homepage = "https://github.com/LLFourn/secp256kfun"
Expand Down
Loading