Fully document crypto/

This commit is contained in:
Luke Parker
2023-03-20 20:10:00 -04:00
parent e1bb2c191b
commit 8d4d630e0f
45 changed files with 335 additions and 208 deletions

View File

@@ -22,6 +22,7 @@ macro_rules! dalek_curve {
const CONTEXT: &'static [u8] = $CONTEXT;
}
/// The challenge function for this ciphersuite.
#[derive(Copy, Clone)]
pub struct $Hram;
impl Hram<$Curve> for $Hram {

View File

@@ -11,11 +11,12 @@ impl Curve for Ed448 {
const CONTEXT: &'static [u8] = CONTEXT;
}
// The RFC-8032 Ed448 challenge function.
#[derive(Copy, Clone)]
pub struct Ietf8032Ed448Hram;
pub(crate) struct Ietf8032Ed448Hram;
impl Ietf8032Ed448Hram {
#[allow(non_snake_case)]
pub fn hram(context: &[u8], R: &Point, A: &Point, m: &[u8]) -> Scalar {
pub(crate) fn hram(context: &[u8], R: &Point, A: &Point, m: &[u8]) -> Scalar {
Scalar::wide_reduce(
Shake256_114::digest(
[
@@ -32,6 +33,7 @@ impl Ietf8032Ed448Hram {
}
}
/// The challenge function for FROST's Ed448 ciphersuite.
#[derive(Copy, Clone)]
pub struct IetfEd448Hram;
impl Hram<Ed448> for IetfEd448Hram {

View File

@@ -17,6 +17,7 @@ macro_rules! kp_curve {
const CONTEXT: &'static [u8] = $CONTEXT;
}
/// The challenge function for this ciphersuite.
#[derive(Clone)]
pub struct $Hram;
impl Hram<$Curve> for $Hram {

View File

@@ -33,10 +33,14 @@ pub use kp256::{P256, IetfP256Hram};
#[cfg(feature = "ed448")]
mod ed448;
#[cfg(feature = "ed448")]
pub use ed448::{Ed448, Ietf8032Ed448Hram, IetfEd448Hram};
pub use ed448::{Ed448, IetfEd448Hram};
#[cfg(all(test, feature = "ed448"))]
pub(crate) use ed448::Ietf8032Ed448Hram;
/// FROST Ciphersuite, except for the signing algorithm specific H2, making this solely the curve,
/// its associated hash function, and the functions derived from it.
/// FROST Ciphersuite.
///
/// This exclude the signing algorithm specific H2, making this solely the curve, its associated
/// hash function, and the functions derived from it.
pub trait Curve: Ciphersuite {
/// Context string for this curve.
const CONTEXT: &'static [u8];
@@ -98,6 +102,7 @@ pub trait Curve: Ciphersuite {
res
}
/// Read a point from a reader, rejecting identity.
#[allow(non_snake_case)]
fn read_G<R: Read>(reader: &mut R) -> io::Result<Self::G> {
let res = <Self as Ciphersuite>::read_G(reader)?;

View File

@@ -1,17 +1,5 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
//! A modular implementation of FROST for any curve with a ff/group API.
//! Additionally, custom algorithms may be specified so any signature reducible to
//! Schnorr-like may be used with FROST.
//!
//! A Schnorr algorithm is provided, of the form (R, s) where `s = r + cx`, which
//! allows specifying the challenge format. This is intended to easily allow
//! integrating with existing systems.
//!
//! This library offers ciphersuites compatible with the
//! [IETF draft](https://github.com/cfrg/draft-irtf-cfrg-frost). Currently, version
//! 11 is supported.
#![doc = include_str!("../README.md")]
use core::fmt::Debug;
use std::collections::HashMap;
@@ -53,12 +41,9 @@ pub enum FrostError {
InvalidPreprocess(Participant),
#[error("invalid share (participant {0})")]
InvalidShare(Participant),
#[error("internal error ({0})")]
InternalError(&'static str),
}
// Validate a map of values to have the expected included participants
/// Validate a map of values to have the expected participants.
pub fn validate_map<T>(
map: &HashMap<Participant, T>,
included: &[Participant],

View File

@@ -43,9 +43,9 @@ impl<T: Writable> Writable for Vec<T> {
}
}
/// Pairing of an Algorithm with a ThresholdKeys instance and this specific signing set.
// Pairing of an Algorithm with a ThresholdKeys instance.
#[derive(Clone, Zeroize)]
pub struct Params<C: Curve, A: Algorithm<C>> {
struct Params<C: Curve, A: Algorithm<C>> {
// Skips the algorithm due to being too large a bound to feasibly enforce on users
#[zeroize(skip)]
algorithm: A,
@@ -53,11 +53,11 @@ pub struct Params<C: Curve, A: Algorithm<C>> {
}
impl<C: Curve, A: Algorithm<C>> Params<C, A> {
pub fn new(algorithm: A, keys: ThresholdKeys<C>) -> Params<C, A> {
fn new(algorithm: A, keys: ThresholdKeys<C>) -> Params<C, A> {
Params { algorithm, keys }
}
pub fn multisig_params(&self) -> ThresholdParams {
fn multisig_params(&self) -> ThresholdParams {
self.keys.params()
}
}
@@ -66,6 +66,7 @@ impl<C: Curve, A: Algorithm<C>> Params<C, A> {
#[derive(Clone, PartialEq, Eq)]
pub struct Preprocess<C: Curve, A: Addendum> {
pub(crate) commitments: Commitments<C>,
/// The addendum used by the algorithm.
pub addendum: A,
}
@@ -76,9 +77,11 @@ impl<C: Curve, A: Addendum> Writable for Preprocess<C, A> {
}
}
/// A cached preprocess. A preprocess MUST only be used once. Reuse will enable third-party
/// recovery of your private key share. Additionally, this MUST be handled with the same security
/// as your private key share, as knowledge of it also enables recovery.
/// A cached preprocess.
///
/// A preprocess MUST only be used once. Reuse will enable third-party recovery of your private
/// key share. Additionally, this MUST be handled with the same security as your private key share,
/// as knowledge of it also enables recovery.
// Directly exposes the [u8; 32] member to void needing to route through std::io interfaces.
// Still uses Zeroizing internally so when users grab it, they have a higher likelihood of
// appreciating how to handle it and don't immediately start copying it just by grabbing it.
@@ -510,6 +513,6 @@ impl<C: Curve, A: Algorithm<C>> SignatureMachine<A::Signature> for AlgorithmSign
}
// If everyone has a valid share, and there were enough participants, this should've worked
Err(FrostError::InternalError("everyone had a valid share yet the signature was still invalid"))
panic!("everyone had a valid share yet the signature was still invalid");
}
}

View File

@@ -203,7 +203,7 @@ pub fn test_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
assert!(sig.verify(group_key, H::hram(&sig.R, &group_key, MSG)));
}
// Test an offset Schnorr signature.
/// Test an offset Schnorr signature.
pub fn test_offset_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
const MSG: &[u8] = b"Hello, World!";
@@ -223,7 +223,7 @@ pub fn test_offset_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &m
assert!(sig.verify(offset_key, H::hram(&sig.R, &group_key, MSG)));
}
// Test blame for an invalid Schnorr signature share.
/// Test blame for an invalid Schnorr signature share.
pub fn test_schnorr_blame<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
const MSG: &[u8] = b"Hello, World!";
@@ -245,7 +245,7 @@ pub fn test_schnorr_blame<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mu
}
}
// Run a variety of tests against a ciphersuite.
/// Run a variety of tests against a ciphersuite.
pub fn test_ciphersuite<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
test_schnorr::<R, C, H>(rng);
test_offset_schnorr::<R, C, H>(rng);

View File

@@ -22,6 +22,7 @@ use crate::{
tests::{clone_without, recover_key, test_ciphersuite},
};
/// Vectors for a ciphersuite.
pub struct Vectors {
pub threshold: u16,
@@ -141,6 +142,7 @@ fn vectors_to_multisig_keys<C: Curve>(vectors: &Vectors) -> HashMap<Participant,
keys
}
/// Test a Ciphersuite with its vectors.
pub fn test_with_vectors<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
rng: &mut R,
vectors: Vectors,