mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Smash dkg into dkg, dkg-[recovery, promote, musig, pedpop]
promote and pedpop require dleq, which don't support no-std. All three should be moved outside the Serai repository, per #597, as none are planned for use and worth covering under our BBP.
This commit is contained in:
34
crypto/dkg/recovery/Cargo.toml
Normal file
34
crypto/dkg/recovery/Cargo.toml
Normal file
@@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "dkg-recovery"
|
||||
version = "0.6.0"
|
||||
description = "Recover a secret-shared key from a collection of dkg::ThresholdKeys"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/serai-dex/serai/tree/develop/crypto/dkg/recovery"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
keywords = ["dkg", "multisig", "threshold", "ff", "group"]
|
||||
edition = "2021"
|
||||
rust-version = "1.80"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
zeroize = { version = "^1.5", default-features = false }
|
||||
|
||||
thiserror = { version = "2", default-features = false }
|
||||
|
||||
ciphersuite = { path = "../../ciphersuite", version = "^0.4.1", default-features = false, features = ["alloc"] }
|
||||
dkg = { path = "../", default-features = false }
|
||||
|
||||
[features]
|
||||
std = [
|
||||
"zeroize/std",
|
||||
"thiserror/std",
|
||||
"ciphersuite/std",
|
||||
"dkg/std",
|
||||
]
|
||||
default = ["std"]
|
||||
21
crypto/dkg/recovery/LICENSE
Normal file
21
crypto/dkg/recovery/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-2025 Luke Parker
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
14
crypto/dkg/recovery/README.md
Normal file
14
crypto/dkg/recovery/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Distributed Key Generation
|
||||
|
||||
A crate implementing a type for keys, presumably the result of a distributed key generation
|
||||
protocol, and utilities from there.
|
||||
|
||||
This crate used to host implementations of distributed key generation protocols as well (hence the
|
||||
name). Those have been smashed into their own crates, such as
|
||||
[`dkg-musig`](https://docs.rs/dkg-musig) and [`dkg-pedpop`](https://docs.rs/dkg-pedpop)
|
||||
|
||||
Before being smashed, this crate was [audited by Cypher Stack in March 2023](
|
||||
https://github.com/serai-dex/serai/raw/e1bb2c191b7123fd260d008e31656d090d559d21/audits/Cypher%20Stack%20crypto%20March%202023/Audit.pdf
|
||||
), culminating in commit [669d2dbffc1dafb82a09d9419ea182667115df06](
|
||||
https://github.com/serai-dex/serai/tree/669d2dbffc1dafb82a09d9419ea182667115df06
|
||||
). Any subsequent changes have not undergone auditing.
|
||||
85
crypto/dkg/recovery/src/lib.rs
Normal file
85
crypto/dkg/recovery/src/lib.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc = include_str!("../README.md")]
|
||||
#![no_std]
|
||||
|
||||
use core::ops::{Deref, DerefMut};
|
||||
extern crate alloc;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use ciphersuite::Ciphersuite;
|
||||
|
||||
pub use dkg::*;
|
||||
|
||||
/// Errors encountered when recovering a secret-shared key from a collection of
|
||||
/// `dkg::ThresholdKeys`.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, thiserror::Error)]
|
||||
pub enum RecoveryError {
|
||||
/// No keys were provided.
|
||||
#[error("no keys provided")]
|
||||
NoKeysProvided,
|
||||
/// Not enough keys were provided.
|
||||
#[error("not enough keys provided (threshold required {required}, provided {provided})")]
|
||||
NotEnoughKeysProvided { required: u16, provided: usize },
|
||||
/// The keys had inconsistent parameters.
|
||||
#[error("keys had inconsistent parameters")]
|
||||
InconsistentParameters,
|
||||
/// The keys are from distinct secret-sharing sessions or otherwise corrupt.
|
||||
#[error("recovery failed")]
|
||||
Failure,
|
||||
/// An error propagated from the underlying `dkg` crate.
|
||||
#[error("error from dkg ({0})")]
|
||||
DkgError(DkgError),
|
||||
}
|
||||
|
||||
/// Recover a shared secret from a collection of `dkg::ThresholdKeys`.
|
||||
pub fn recover_key<C: Ciphersuite>(
|
||||
keys: &[ThresholdKeys<C>],
|
||||
) -> Result<Zeroizing<C::F>, RecoveryError> {
|
||||
let included = keys.iter().map(|keys| keys.params().i()).collect::<Vec<_>>();
|
||||
|
||||
let keys_len = keys.len();
|
||||
let mut keys = keys.iter();
|
||||
let first_keys = keys.next().ok_or(RecoveryError::NoKeysProvided)?;
|
||||
{
|
||||
let t = first_keys.params().t();
|
||||
if keys_len < usize::from(t) {
|
||||
Err(RecoveryError::NotEnoughKeysProvided { required: t, provided: keys_len })?;
|
||||
}
|
||||
}
|
||||
{
|
||||
let first_params = (
|
||||
first_keys.params().t(),
|
||||
first_keys.params().n(),
|
||||
first_keys.group_key(),
|
||||
first_keys.current_scalar(),
|
||||
first_keys.current_offset(),
|
||||
);
|
||||
for keys in keys.clone() {
|
||||
let params = (
|
||||
keys.params().t(),
|
||||
keys.params().n(),
|
||||
keys.group_key(),
|
||||
keys.current_scalar(),
|
||||
keys.current_offset(),
|
||||
);
|
||||
if params != first_params {
|
||||
Err(RecoveryError::InconsistentParameters)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut res: Zeroizing<_> =
|
||||
first_keys.view(included.clone()).map_err(RecoveryError::DkgError)?.secret_share().clone();
|
||||
for keys in keys {
|
||||
*res.deref_mut() +=
|
||||
keys.view(included.clone()).map_err(RecoveryError::DkgError)?.secret_share().deref();
|
||||
}
|
||||
|
||||
if (C::generator() * res.deref()) != first_keys.group_key() {
|
||||
Err(RecoveryError::Failure)?;
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
Reference in New Issue
Block a user