Skip to content

Commit

Permalink
Merge pull request #100 from dfns/sync-api
Browse files Browse the repository at this point in the history
Update `round-based` dep
  • Loading branch information
survived committed May 23, 2024
2 parents 33320b9 + ffe0714 commit 1fc654e
Show file tree
Hide file tree
Showing 27 changed files with 1,532 additions and 460 deletions.
15 changes: 13 additions & 2 deletions .github/workflows/readme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,20 @@ jobs:
- name: Install cargo-hakari
uses: baptiste0928/cargo-install@v1
with:
crate: cargo-readme
crate: cargo-rdme
- name: Check that readme matches lib.rs
run: |
cp README.md README-copy.md
make readme
diff README.md README-copy.md
diff README.md README-copy.md
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install toc-markdown
run: npm install -g markdown-toc
- name: Check that table of contents matches docs/toc-cggmp21.md
run: |
cp docs/toc-cggmp21.md docs/toc-cggmp21-copy.md
make toc-cggmp21
diff docs/toc-cggmp21.md docs/toc-cggmp21-copy.md
27 changes: 8 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,22 @@ docs-private:
RUSTDOCFLAGS="--html-in-header katex-header.html --cfg docsrs" cargo +nightly doc --all-features --no-deps --document-private-items

readme:
cargo readme -i src/lib.rs -r cggmp21/ -t ../docs/README.tpl --no-indent-headings \
cargo rdme -w cggmp21 -r README.md && \
cat README.md \
| sed -E 's/(\/\*.+\*\/)/\1;/' \
| sed -E '/^\[`.+`\]:/d' \
| sed -E 's/\[`([^`]*)`\]\(.+?\)/`\1`/g' \
| sed -E 's/\[`([^`]*)`\]/`\1`/g' \
| perl -ne 's/(?<!!)\[([^\[]+?)\]\([^\(]+?\)/\1/g; print;' \
| sed -E '/^#$$/d' \
> README.md
| sed -e '/<!-- TOC -->/{r docs/toc-cggmp21.md' -e 'd}' \
> README-2.md && \
mv README-2.md README.md

toc-cggmp21:
echo '<!-- TOC STARTS -->' > docs/toc-cggmp21.md
echo >> docs/toc-cggmp21.md
markdown-toc --no-firsth1 - < README.md >> docs/toc-cggmp21.md
echo >> docs/toc-cggmp21.md
echo >> docs/toc-cggmp21.md
echo '<!-- TOC ENDS -->' >> docs/toc-cggmp21.md
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
<!-- cargo-rdme start -->

![License](https://img.shields.io/crates/l/cggmp21.svg)
[![Docs](https://docs.rs/cggmp21/badge.svg)](https://docs.rs/cggmp21)
[![Crates io](https://img.shields.io/crates/v/cggmp21.svg)](https://crates.io/crates/cggmp21)

# Threshold ECDSA based on [CGGMP21] paper

<!-- TOC STARTS -->

- [Running the protocol](#running-the-protocol)
* [Networking](#networking)
+ [Signer indices](#signer-indices)
* [Execution ID](#execution-id)
* [Auxiliary info generation](#auxiliary-info-generation)
+ [On reusability of the auxiliary data](#on-reusability-of-the-auxiliary-data)
* [Distributed Key Generation (DKG)](#distributed-key-generation-dkg)
* [Signing](#signing)
- [Sync API](#sync-api)
- [HD wallets support](#hd-wallets-support)
- [SPOF code: Key Import and Export](#spof-code-key-import-and-export)
- [Differences between the implementation and CGGMP21](#differences-between-the-implementation-and-cggmp21)
- [Timing attacks](#timing-attacks)

<!-- TOC ENDS -->

[CGGMP21] is a state-of-art ECDSA TSS protocol that supports 1-round signing (requires preprocessing),
identifiable abort, provides two signing protocols (3+1 and 5+1 rounds with different complexity
of abort identification) and key refresh protocol out of the box.
Expand Down Expand Up @@ -179,6 +199,15 @@ Alternatively, you can generate a presignature and later use it to sign:
**Never reuse presignatures!** If you use the same presignature to sign two different messages,
the private key may be leaked.

## Sync API
Every protocol is defined as async function. If you need to run a protocol in non-async environment,
library provides a wrapper that allows you to execute protocol using sync API only.

To use it, you need to enable `state-machine` feature. Then, for every protocol definition, you can
find a companion function that returns `StateMachine`
which can be used to carry out the protocol. For instance, if you do presignature generation, use
`signing::SigningBuilder::generate_presignature_sync`.

## HD wallets support
Library supports non-hardened deterministic key derivation based on [slip10] standard (compatible
with [bip32]). It allows signers to generate a master key once, and then use it to instantaneously
Expand All @@ -202,7 +231,7 @@ Such use-cases contradict to nature of MPC so we don't include those primitives
However, you may opt for them by enabling `spof` feature, then you can use `trusted_dealer`
for key import and `key_share::reconstruct_secret_key` for key export.

## Differences between the implementation and [CGGMP21]
## Differences between the implementation and CGGMP21
[CGGMP21] only defines a non-threshold protocol. To support general thresholds,
we defined our own CGGMP21-like key generation and threshold signing
protocols. However, we keep both
Expand All @@ -218,9 +247,12 @@ they are all documented in [the spec].
[slip10]: https://github.com/satoshilabs/slips/blob/master/slip-0010.md
[bip32]: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
[report]: https://github.com/dfns/cggmp21/blob/m/docs/audit_report.pdf
[serde]: https://serde.rs/

## Timing attacks
Timing attacks are type of side-channel attacks that leak sensitive information through duration of
execution. We consider timing attacks out of scope as they are nearly impossible to perform for such
complicated protcol as CGGMP21 and impossible to do in our specific deployment. Thus, we intentionally
don't do constant-time operations which gives us a significant performance boost.

<!-- cargo-rdme end -->
7 changes: 7 additions & 0 deletions cggmp21-keygen/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v0.2.0
* Make library `#![no_std]`-compatible and WASM-friendly [#100]
* Provide sync API to carry out DKG protocol [#100]
* Update `round-based` dep to `v0.3`

[#100]: https://github.com/dfns/cggmp21/pull/100

## v0.1.0

Initial release
32 changes: 18 additions & 14 deletions cggmp21-keygen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cggmp21-keygen"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "UC-secure DKG implementation based on CGGMP21 paper"
Expand All @@ -11,25 +11,29 @@ keywords = ["mpc", "dkg", "threshold-signatures", "tss"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
key-share = { path = "../key-share", version = "0.2", features = ["serde"] }
slip-10 = { version = "0.2", optional = true }
key-share = { path = "../key-share", version = "0.2", default-features = false, features = ["serde"] }
slip-10 = { version = "0.2", default-features = false, optional = true }

generic-ec = { version = "0.2", features = ["serde", "udigest"] }
generic-ec-zkp = { version = "0.2", features = ["serde", "udigest"] }
udigest = { version = "0.1", features = ["std", "derive"]}
generic-ec = { version = "0.2", default-features = false, features = ["serde", "udigest"] }
generic-ec-zkp = { version = "0.2", default-features = false, features = ["serde", "udigest"] }
udigest = { version = "0.1", default-features = false, features = ["derive"]}

round-based = { version = "0.2", features = ["derive"] }
futures = "0.3"
round-based = { version = "0.3", default-features = false, features = ["derive"] }

sha2 = "0.10"
digest = "0.10"
rand_core = "0.6"
sha2 = { version = "0.10", default-features = false }
digest = { version = "0.10", default-features = false }
rand_core = { version = "0.6", default-features = false }

serde = { version = "1", features = ["derive"] }
serde_with = { version = "2" }
serde = { version = "1", default-features = false, features = ["derive"] }
serde_with = { version = "2", default-features = false }
hex = { version = "0.4", default-features = false, features = ["serde"] }

thiserror = "1"
displaydoc = { version = "0.2", default-features = false }
thiserror = { version = "1", optional = true }

[features]
default = ["std"]

std = ["thiserror", "key-share/std", "udigest/std", "round-based/std"]
hd-wallets = ["slip-10", "key-share/hd-wallets"]
state-machine = ["round-based/state-machine"]
41 changes: 28 additions & 13 deletions cggmp21-keygen/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,46 @@
use std::convert::Infallible;
use alloc::boxed::Box;
use core::convert::Infallible;

use round_based::rounds_router::{
errors::{self as router_error, CompleteRoundError},
simple_store::RoundInputError,
};
use thiserror::Error;

pub type BoxedError = Box<dyn std::error::Error + Send + Sync>;
mod std_error {
#[cfg(feature = "std")]
pub use std::error::Error as StdError;

#[derive(Debug, Error)]
#[cfg(not(feature = "std"))]
pub trait StdError: core::fmt::Display + core::fmt::Debug {}
#[cfg(not(feature = "std"))]
impl<E: core::fmt::Display + core::fmt::Debug> StdError for E {}
}
pub use std_error::StdError;

pub type BoxedError = Box<dyn StdError + Send + Sync>;

#[derive(Debug, displaydoc::Display)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
pub enum IoError {
#[error("send message")]
SendMessage(#[source] BoxedError),
#[error("receive message")]
ReceiveMessage(#[source] BoxedError),
#[error("got eof while recieving messages")]
#[displaydoc("send message")]
SendMessage(#[cfg_attr(feature = "std", source)] BoxedError),
#[displaydoc("receive message")]
ReceiveMessage(#[cfg_attr(feature = "std", source)] BoxedError),
#[displaydoc("got eof while recieving messages")]
ReceiveMessageEof,
#[error("route received message (possibly malicious behavior)")]
RouteReceivedError(router_error::CompleteRoundError<RoundInputError, Infallible>),
#[displaydoc("route received message (possibly malicious behavior)")]
RouteReceivedError(
#[cfg_attr(feature = "std", source)]
router_error::CompleteRoundError<RoundInputError, Infallible>,
),
}

impl IoError {
pub fn send_message<E: std::error::Error + Send + Sync + 'static>(err: E) -> Self {
pub fn send_message<E: StdError + Send + Sync + 'static>(err: E) -> Self {
Self::SendMessage(Box::new(err))
}

pub fn receive_message<E: std::error::Error + Send + Sync + 'static>(
pub fn receive_message<E: StdError + Send + Sync + 'static>(
err: CompleteRoundError<RoundInputError, E>,
) -> Self {
match err {
Expand Down
Loading

0 comments on commit 1fc654e

Please sign in to comment.