diff --git a/README.md b/README.md index 4eeb12c..8d741b6 100644 --- a/README.md +++ b/README.md @@ -8,18 +8,35 @@ into its signature. It leverages the [Arkworks](https://github.com/arkworks-rs) framework and supports customization of scheme parameters. -### Supported Schemes +## What is a VRF? + + A Verifiable Random Function (VRF) is a cryptographic primitive that maps inputs + to verifiable pseudorandom outputs. Key properties include: + + - **Uniqueness**: For a given input and private key, there is exactly one valid output + - **Verifiability**: Anyone with the public key can verify that an output is correct + - **Pseudorandomness**: Without the private key, outputs appear random and unpredictable + - **Collision resistance**: Finding inputs that map to the same output is computationally infeasible + +## Supported Schemes - **IETF VRF**: Complies with ECVRF described in [RFC9381](https://datatracker.ietf.org/doc/rfc9381). + This is a standardized VRF implementation suitable for most applications requiring + verifiable randomness. + - **Pedersen VRF**: Described in [BCHSV23](https://eprint.iacr.org/2023/002). -- **Ring VRF**: A zero-knowledge-based inspired by [BCHSV23](https://eprint.iacr.org/2023/002). + Extends the basic VRF with key-hiding properties using Pedersen commitments, + +- **Ring VRF**: A zero-knowledge-based scheme inspired by [BCHSV23](https://eprint.iacr.org/2023/002). + Provides signer anonymity within a set of public keys (a "ring"), allowing + verification that a ring member created the proof without revealing which specific member. -### Schemes Specifications +### Specifications -- [VRF Schemes Details](https://github.com/davxy/bandersnatch-vrf-spec) -- [Ring VRF ZK Proof](https://github.com/davxy/ring-proof-spec) +- [VRF Schemes](https://github.com/davxy/bandersnatch-vrf-spec) +- [Ring Proof](https://github.com/davxy/ring-proof-spec) -### Built-In suites +## Built-In suites The library conditionally includes the following pre-configured suites (see features section): @@ -29,68 +46,159 @@ The library conditionally includes the following pre-configured suites (see feat - **JubJub** (_Edwards curve on BLS12-381_): Supports IETF, Pedersen, and Ring VRF. - **Baby-JubJub** (_Edwards curve on BN254_): Supports IETF, Pedersen, and Ring VRF. -### Basic Usage +## Basic Usage ```rust use ark_vrf::suites::bandersnatch::*; + +// Create a secret key from a seed let secret = Secret::from_seed(b"example seed"); + +// Derive the corresponding public key let public = secret.public(); + +// Create an input by hashing date to a curve point let input = Input::new(b"example input"); + +// Compute the VRF output (gamma point) let output = secret.output(input); + +// Optional additional data that can be bound to the proof let aux_data = b"optional aux data"; ``` -#### IETF-VRF + +The VRF output can be hashed to obtain a pseudorandom byte string: + +```rust +// Get a deterministic hash from the VRF output point +let hash_bytes = output.hash(); +``` + +### IETF-VRF + +The IETF VRF scheme follows [RFC-9381](https://datatracker.ietf.org/doc/rfc9381) +and provides a standardized approach to verifiable random functions. _Prove_ ```rust use ark_vrf::ietf::Prover; + +// Generate a proof that binds the input, output, and auxiliary data let proof = secret.prove(input, output, aux_data); + +// The proof can be serialized for transmission +let serialized_proof = proof.to_bytes(); ``` _Verify_ ```rust use ark_vrf::ietf::Verifier; + +// Verify the proof against the public key let result = public.verify(input, output, aux_data, &proof); +assert!(result.is_ok()); + +// Verification will fail if any parameter is modified +let tampered_output = secret.output(Input::new(b"different input").unwrap()); +assert!(public.verify(input, tampered_output, aux_data, &proof).is_err()); +``` + +### Pedersen-VRF + +The Pedersen VRF extends the IETF scheme with key-hiding properties using Pedersen commitments. + +_Prove_ +```rust +use ark_vrf::pedersen::Prover; + +// Generate a proof with a blinding factor +let (proof, blinding) = secret.prove(input, output, aux_data); + +// The proof includes a commitment to the public key +let key_commitment = proof.key_commitment(); ``` -#### Ring-VRF +_Verify_ +```rust +use ark_vrf::pedersen::Verifier; + +// Verify without knowing which specific public key was used. +// Verifiers that the secret key used to generate `output` is the same as +// the secret key used to generate `proof.key_commitment()`. +let result = Public::verify(input, output, aux_data, &proof); +assert!(result.is_ok()); + +// Verify the proof was created using a specific public key +// This requires knowledge of the blinding factor +let expected_commitment = (public.0 + MySuite::BLINDING_BASE * blinding).into_affine(); +assert_eq!(proof.key_commitment(), expected_commitment); +``` +### Ring-VRF + +The Ring VRF provides anonymity within a set of public keys using zero-knowledge proofs. + _Ring construction_ ```rust const RING_SIZE: usize = 100; let prover_key_index = 3; + // Construct an example ring with dummy keys -let mut ring = (0..RING_SIZE).map(|i| Secret::from_seed(&i.to_le_bytes()).public().0).collect(); +let mut ring = (0..RING_SIZE) + .map(|i| Secret::from_seed(&i.to_le_bytes()).public().0) + .collect::>(); + // Patch the ring with the public key of the prover ring[prover_key_index] = public.0; + // Any key can be replaced with the padding point ring[0] = RingProofParams::padding_point(); -``` -_Ring parameters construction_ -```rust +// Create parameters for the ring proof system. +// These parameters are reusable across multiple proofs let params = RingProofParams::from_seed(RING_SIZE, b"example seed"); ``` _Prove_ ```rust use ark_vrf::ring::Prover; + +// Create a prover key specific to this ring let prover_key = params.prover_key(&ring); + +// Create a prover instance for the specific position in the ring let prover = params.prover(prover_key, prover_key_index); + +// Generate a zero-knowledge proof that: +// 1. The prover knows a secret key for one of the public keys in the ring +// 2. That secret key was used to generate the VRF output let proof = secret.prove(input, output, aux_data, &prover); ``` _Verify_ ```rust use ark_vrf::ring::Verifier; + +// Create a verifier key for this ring let verifier_key = params.verifier_key(&ring); + +// Create a verifier instance let verifier = params.verifier(verifier_key); + +// Verify the proof - this confirms that: +// 1. The proof was created by someone who knows a secret key in the ring +// 2. The VRF output is correct for the given input +// But it does NOT reveal which ring member created the proof let result = Public::verify(input, output, aux_data, &proof, &verifier); ``` _Verifier key from commitment_ ```rust +// For efficiency, a commitment to the ring can be shared let ring_commitment = params.verifier_key().commitment(); + +// A verifier can reconstruct the verifier key from just the commitment +// without needing the full ring of public keys let verifier_key = params.verifier_key_from_commitment(ring_commitment); ``` diff --git a/src/ietf.rs b/src/ietf.rs index 4baa45f..3a2435d 100644 --- a/src/ietf.rs +++ b/src/ietf.rs @@ -1,8 +1,28 @@ -//! EC-VRF as specified by [RFC-9381](https://datatracker.ietf.org/doc/rfc9381). +//! # IETF-VRF //! -//! The implementation extends RFC9381 to allow to sign additional user data together -//! with the VRF input. Refer to for -//! specification extension details. +//! Implementation of the ECVRF scheme defined in [RFC-9381](https://datatracker.ietf.org/doc/rfc9381), +//! extended to support binding additional data to the proof. +//! +//! The extension specification is available at: +//! +//! +//! ## Usage Example +//! +//! ```rust,ignore +//! // Key generation +//! let secret = Secret::::from_seed(b"seed"); +//! let public = secret.public(); +//! +//! // Proving +//! use ark_vrf::ietf::Prover; +//! let input = Input::from(my_data); +//! let output = secret.output(input); +//! let proof = secret.prove(input, output, aux_data); +//! +//! // Verification +//! use ark_vrf::ietf::Verifier; +//! let result = public.verify(input, output, aux_data, &proof); +//! ``` use super::*; @@ -11,6 +31,10 @@ pub trait IetfSuite: Suite {} impl IetfSuite for T where T: Suite {} /// IETF VRF proof. +/// +/// Schnorr-based proof of correctness for a VRF evaluation: +/// - `c`: Challenge scalar derived from public parameters +/// - `s`: Response scalar satisfying the verification equation #[derive(Debug, Clone)] pub struct Proof { pub c: ScalarField, @@ -71,13 +95,38 @@ impl ark_serialize::Valid for Proof { } } +/// Trait for types that can generate VRF proofs. +/// +/// Implementors can create cryptographic proofs that a VRF output +/// is correctly derived from an input using their secret key. pub trait Prover { - /// Generate a proof for the given input/output and user additional data. + /// Generate a proof for the given input/output and additional data. + /// + /// Creates a non-interactive zero-knowledge proof binding the input, output, + /// and additional data to the prover's public key. + /// + /// * `input` - VRF input point + /// * `output` - VRF output point (γ = x·H) + /// * `ad` - Additional data to bind to the proof fn prove(&self, input: Input, output: Output, ad: impl AsRef<[u8]>) -> Proof; } +/// Trait for entities that can verify VRF proofs. +/// +/// Implementors can verify that a VRF output is correctly derived +/// from an input using a specific public key. pub trait Verifier { - /// Verify a proof for the given input/output and user additional data. + /// Verify a proof for the given input/output and additional data. + /// + /// Verifies the cryptographic relationship between input, output, and proof + /// under the verifier's public key. + /// + /// * `input` - VRF input point + /// * `output` - Claimed VRF output point + /// * `aux` - Additional data bound to the proof + /// * `proof` - The proof to verify + /// + /// Returns `Ok(())` if verification succeeds, `Err(Error::VerificationFailure)` otherwise. fn verify( &self, input: Input, @@ -88,6 +137,16 @@ pub trait Verifier { } impl Prover for Secret { + /// Implements the IETF VRF proving algorithm. + /// + /// This follows the procedure specified in RFC-9381 section 5.1, with extensions + /// to support binding additional data to the proof: + /// + /// 1. Generate a deterministic nonce `k` based on the secret key and input + /// 2. Compute nonce commitments `k_b` and `k_h` + /// 3. Compute the challenge `c` using all public values, nonce commitments and the + /// additional data + /// 4. Compute the response `s = k + c * secret` fn prove(&self, input: Input, output: Output, ad: impl AsRef<[u8]>) -> Proof { let k = S::nonce(&self.scalar, input); @@ -104,6 +163,16 @@ impl Prover for Secret { } impl Verifier for Public { + /// Implements the IETF VRF verification algorithm. + /// + /// This follows the procedure specified in RFC-9381 section 5.3, with extensions + /// to support verifying additional data bound to the proof: + /// + /// 1. Compute `u = s*G - c*Y` where G is the generator and Y is the public key + /// 2. Compute `v = s*H - c*O` where H is the input point and O is the output point + /// 3. Recompute the expected challenge `c_exp` using all public values, `u`, `v` and + /// the additional data + /// 4. Verify that `c_exp == c` from the proof fn verify( &self, input: Input, diff --git a/src/lib.rs b/src/lib.rs index 470bb69..2c86af1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,25 +1,28 @@ //! # Elliptic Curve VRF-AD //! -//! This library provides flexible and efficient implementations of Verifiable -//! Random Functions with Additional Data (VRF-AD), a cryptographic construct -//! that augments a standard VRF scheme by incorporating auxiliary information -//! into its signature. +//! Implementations of Verifiable Random Functions with Additional Data (VRF-AD) +//! based on elliptic curve cryptography. Built on the [Arkworks](https://github.com/arkworks-rs) +//! framework with configurable cryptographic parameters. //! -//! It leverages the [Arkworks](https://github.com/arkworks-rs) framework and -//! supports customization of scheme parameters. +//! VRF-AD extends standard VRF constructions by binding auxiliary data to the proof, +//! providing stronger contextual security guarantees. //! -//! ### Supported Schemes +//! ## Schemes //! -//! - **IETF VRF**: Complies with ECVRF described in [RFC9381](https://datatracker.ietf.org/doc/rfc9381). -//! - **Pedersen VRF**: Described in [BCHSV23](https://eprint.iacr.org/2023/002). -//! - **Ring VRF**: A zero-knowledge-based inspired by [BCHSV23](https://eprint.iacr.org/2023/002). +//! - **IETF VRF**: ECVRF implementation compliant with [RFC9381](https://datatracker.ietf.org/doc/rfc9381) //! -//! ### Schemes Specifications +//! - **Pedersen VRF**: Key-hiding VRF using Pedersen commitments as described in +//! [BCHSV23](https://eprint.iacr.org/2023/002) //! -//! - [VRF Schemes Details](https://github.com/davxy/bandersnatch-vrf-spec) -//! - [Ring VRF ZK Proof](https://github.com/davxy/ring-proof-spec) +//! - **Ring VRF**: Zero-knowledge VRF with signer anonymity within a key set, based on +//! [BCHSV23](https://eprint.iacr.org/2023/002) //! -//! ### Built-In suites +//! ### Specifications +//! +//! - [VRF Schemes](https://github.com/davxy/bandersnatch-vrf-spec) +//! - [Ring Proof](https://github.com/davxy/ring-proof-spec) +//! +//! ## Built-In suites //! //! The library conditionally includes the following pre-configured suites (see features section): //! @@ -29,70 +32,23 @@ //! - **JubJub** (_Edwards curve on BLS12-381_): Supports IETF, Pedersen, and Ring VRF. //! - **Baby-JubJub** (_Edwards curve on BN254_): Supports IETF, Pedersen, and Ring VRF. //! -//! ### Basic Usage +//! ## Usage //! //! ```rust,ignore //! use ark_vrf::suites::bandersnatch::*; +//! //! let secret = Secret::from_seed(b"example seed"); //! let public = secret.public(); //! let input = Input::new(b"example input").unwrap(); //! let output = secret.output(input); -//! let aux_data = b"optional aux data"; -//! ``` -//! #### IETF-VRF -//! -//! _Prove_ -//! ```rust,ignore -//! use ark_vrf::ietf::Prover; -//! let proof = secret.prove(input, output, aux_data); -//! ``` -//! -//! _Verify_ -//! ```rust,ignore -//! use ark_vrf::ietf::Verifier; -//! let result = public.verify(input, output, aux_data, &proof); -//! ``` -//! -//! #### Ring-VRF -//! -//! _Ring construction_ -//! ```rust,ignore -//! const RING_SIZE: usize = 100; -//! let prover_key_index = 3; -//! // Construct an example ring with dummy keys -//! let mut ring = (0..RING_SIZE).map(|i| Secret::from_seed(&i.to_le_bytes()).public().0).collect(); -//! // Patch the ring with the public key of the prover -//! ring[prover_key_index] = public.0; -//! // Any key can be replaced with the padding point -//! ring[0] = RingProofParams::padding_point(); -//! ``` -//! -//! _Ring parameters construction_ -//! ```rust,ignore -//! let params = RingProofParams::from_seed(RING_SIZE, b"example seed"); -//! ``` -//! -//! _Prove_ -//! ```rust,ignore -//! use ark_vrf::ring::Prover; -//! let prover_key = params.prover_key(&ring); -//! let prover = params.prover(prover_key, prover_key_index); -//! let proof = secret.prove(input, output, aux_data, &prover); +//! let hash_bytes = output.hash(); //! ``` //! -//! _Verify_ -//! ```rust,ignore -//! use ark_vrf::ring::Verifier; -//! let verifier_key = params.verifier_key(&ring); -//! let verifier = params.verifier(verifier_key); -//! let result = Public::verify(input, output, aux_data, &proof, &verifier); -//! ``` +//! ### Proof Generation Schemes //! -//! _Verifier key from commitment_ -//! ```rust,ignore -//! let ring_commitment = params.verifier_key().commitment(); -//! let verifier_key = params.verifier_key_from_commitment(ring_commitment); -//! ``` +//! - [ietf] vrf proof +//! - [pedersen] vrf proof +//! - [ring] vrf proof //! //! ## Features //! @@ -268,7 +224,10 @@ pub trait Suite: Copy { } } -/// Secret key. +/// Secret key for VRF operations. +/// +/// Contains the private scalar and cached public key. +/// Implements automatic zeroization on drop. #[derive(Debug, Clone, PartialEq)] pub struct Secret { // Secret scalar. @@ -354,22 +313,30 @@ impl Secret { } /// Public key generic over the cipher suite. +/// +/// Elliptic curve point representing the public component of a VRF key pair. #[derive(Debug, Copy, Clone, PartialEq, CanonicalSerialize, CanonicalDeserialize)] pub struct Public(pub AffinePoint); impl Public { /// Construct from inner affine point. + /// + /// This allows creating a public key from an existing curve point. pub fn from(value: AffinePoint) -> Self { Self(value) } } /// VRF input point generic over the cipher suite. +/// +/// Elliptic curve point representing the VRF input. #[derive(Debug, Clone, Copy, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize)] pub struct Input(pub AffinePoint); impl Input { /// Construct from [`Suite::data_to_point`]. + /// + /// Maps arbitrary data to a curve point via hash-to-curve. pub fn new(data: &[u8]) -> Option { S::data_to_point(data).map(Input) } @@ -381,16 +348,20 @@ impl Input { } /// VRF output point generic over the cipher suite. +/// +/// Elliptic curve point representing the VRF output. #[derive(Debug, Clone, Copy, PartialEq, Eq, CanonicalSerialize, CanonicalDeserialize)] pub struct Output(pub AffinePoint); impl Output { /// Construct from inner affine point. + /// + /// This allows creating an output from an existing curve point. pub fn from(value: AffinePoint) -> Self { Self(value) } - /// Hash using `[Suite::point_to_hash]`. + /// Hash the output point to a deterministic byte string. pub fn hash(&self) -> HashOutput { S::point_to_hash(&self.0) } diff --git a/src/pedersen.rs b/src/pedersen.rs index 575291c..a27064a 100644 --- a/src/pedersen.rs +++ b/src/pedersen.rs @@ -1,4 +1,33 @@ -//! Pedersen VRF +//! # Pedersen-VRF +//! +//! Implementation of a key-hiding VRF scheme using Pedersen commitments as described in +//! [BCHSV23](https://eprint.iacr.org/2023/002). +//! +//! This scheme extends the IETF VRF by adding key privacy through blinding factors, +//! allowing verification without revealing which specific public key was used. +//! +//! ## Usage Example +//! +//! ```rust,ignore +//! // Key generation +//! let secret = Secret::::from_seed(b"seed"); +//! let public = secret.public(); +//! +//! // Proving +//! use ark_vrf::pedersen::Prover; +//! let input = Input::from(my_data); +//! let output = secret.output(input); +//! let (proof, blinding) = secret.prove(input, output, aux_data); +//! +//! // Verification +//! use ark_vrf::pedersen::Verifier; +//! let result = Public::verify(input, output, aux_data, &proof); +//! +//! // Verify the proof was created using a specific public key +//! // This requires knowledge of the blinding factor +//! let expected_commitment = (public.0 + MySuite::BLINDING_BASE * blinding).into_affine(); +//! assert_eq!(proof.key_commitment(), expected_commitment); +//! ``` use crate::ietf::IetfSuite; use crate::*; @@ -34,7 +63,14 @@ pub trait PedersenSuite: IetfSuite { } } -/// Pedersen proof. +/// Pedersen VRF proof. +/// +/// Zero-knowledge proof with key-hiding properties: +/// - `pk_com`: Commitment to the public key (Y_b = x·G + b·B) +/// - `r`: Nonce commitment for the generator (R = k·G + k_b·B) +/// - `ok`: Nonce commitment for the input point (O_k = k·I) +/// - `s`: Response scalar for the secret key +/// - `sb`: Response scalar for the blinding factor #[derive(Debug, Clone, CanonicalSerialize, CanonicalDeserialize)] pub struct Proof { pk_com: AffinePoint, @@ -51,8 +87,20 @@ impl Proof { } } +/// Trait for types that can generate Pedersen VRF proofs. +/// +/// Implementors can create zero-knowledge proofs that a VRF output +/// is correctly derived from an input using their secret key, +/// while hiding the specific public key used. pub trait Prover { - /// Generate a proof for the given input/output and user additional data. + /// Generate a proof for the given input/output and additional data. + /// + /// Creates a zero-knowledge proof binding the input, output, and additional data + /// to a commitment of the prover's public key rather than the key itself. + /// + /// * `input` - VRF input point + /// * `output` - VRF output point (γ = x·H) + /// * `ad` - Additional data to bind to the proof /// /// Returns the proof together with the associated blinding factor. fn prove( @@ -63,11 +111,24 @@ pub trait Prover { ) -> (Proof, ScalarField); } +/// Trait for entities that can verify Pedersen VRF proofs. +/// +/// Implementors can verify that a VRF output is correctly derived +/// from an input using a committed public key. pub trait Verifier { - /// Verify a proof for the given input/output and user additional data. + /// Verify a proof for the given input/output and additional data. + /// + /// Verifies the cryptographic relationship between input, output, and proof + /// without requiring knowledge of which specific public key was used. + /// Confirms that the secret key used to generate the output is the same as + /// the one committed to in the proof. + /// + /// * `input` - VRF input point + /// * `output` - Claimed VRF output point + /// * `ad` - Additional data bound to the proof + /// * `proof` - The proof to verify /// - /// Verifiers that the secret key used to generate `output` is the same as - /// the secret key used to generate `proof.key_commitment()`. + /// Returns `Ok(())` if verification succeeds, `Err(Error::VerificationFailure)` otherwise. fn verify( input: Input, output: Output, diff --git a/src/ring.rs b/src/ring.rs index 0bbc633..d523181 100644 --- a/src/ring.rs +++ b/src/ring.rs @@ -1,6 +1,42 @@ -//! Ring VRF. +//! # Ring VRF +//! +//! Implementation of a zero-knowledge VRF scheme providing signer anonymity within a set of +//! public keys, based on [BCHSV23](https://eprint.iacr.org/2023/002). //! //! This module is gated by the `ring` feature. +//! +//! ## Usage Example +//! +//! ```rust,ignore +//! // Ring setup +//! const RING_SIZE: usize = 100; +//! let prover_key_index = 3; +//! +//! // Create a ring of public keys +//! let mut ring = (0..RING_SIZE) +//! .map(|i| Secret::from_seed(&i.to_le_bytes()).public().0) +//! .collect::>(); +//! ring[prover_key_index] = public.0; +//! +//! // Initialize ring parameters +//! let params = RingProofParams::from_seed(RING_SIZE, b"example seed"); +//! +//! // Proving +//! use ark_vrf::ring::Prover; +//! let prover_key = params.prover_key(&ring); +//! let prover = params.prover(prover_key, prover_key_index); +//! let proof = secret.prove(input, output, aux_data, &prover); +//! +//! // Verification +//! use ark_vrf::ring::Verifier; +//! let verifier_key = params.verifier_key(&ring); +//! let verifier = params.verifier(verifier_key); +//! let result = Public::verify(input, output, aux_data, &proof, &verifier); +//! +//! // Efficient verification with commitment +//! let ring_commitment = verifier_key.commitment(); +//! let reconstructed_key = params.verifier_key_from_commitment(ring_commitment); +//! ``` use crate::*; use ark_ec::{ @@ -115,6 +151,10 @@ pub type RingVerifier = pub type RingBareProof = ring_proof::RingProof, Pcs>; /// Ring VRF proof. +/// +/// Two-part zero-knowledge proof with signer anonymity: +/// - `pedersen_proof`: Key commitment and VRF correctness proof +/// - `ring_proof`: Membership proof binding the commitment to the ring #[derive(Clone, CanonicalSerialize, CanonicalDeserialize)] pub struct Proof where @@ -126,7 +166,10 @@ where pub ring_proof: RingBareProof, } -/// Ring VRF prover. +/// Trait for types that can generate Ring VRF proofs. +/// +/// Implementors can create anonymous proofs that a VRF output +/// is correctly derived using a secret key from a ring of public keys. pub trait Prover where BaseField: ark_ff::PrimeField, @@ -134,6 +177,15 @@ where AffinePoint: TEMapping>, { /// Generate a proof for the given input/output and additional data. + /// + /// Creates a zero-knowledge proof that: + /// 1. The prover knows a secret key for one of the ring's public keys + /// 2. That secret key was used to compute the VRF output + /// + /// * `input` - VRF input point + /// * `output` - VRF output point + /// * `ad` - Additional data to bind to the proof + /// * `prover` - Ring prover instance for the specific ring position fn prove( &self, input: Input, @@ -143,14 +195,30 @@ where ) -> Proof; } -/// Ring VRF verifier. +/// Trait for entities that can verify Ring VRF proofs. +/// +/// Implementors can verify anonymous proofs that a VRF output +/// was derived using a secret key from a ring of public keys. pub trait Verifier where BaseField: ark_ff::PrimeField, CurveConfig: TECurveConfig, AffinePoint: TEMapping>, { - /// Verify a proof for the given input/output and user additional data. + /// Verify a proof for the given input/output and additional data. + /// + /// Verifies that: + /// 1. The proof was created by a member of the ring + /// 2. The VRF output is correct for the given input + /// 3. The additional data matches what was used during proving + /// + /// * `input` - VRF input point + /// * `output` - Claimed VRF output point + /// * `ad` - Additional data bound to the proof + /// * `sig` - The proof to verify + /// * `verifier` - Ring verifier instance for the specific ring + /// + /// Returns `Ok(())` if verification succeeds, `Err(Error::VerificationFailure)` otherwise. fn verify( input: Input, output: Output, @@ -207,9 +275,11 @@ where } } -/// Ring proof full parameters. +/// Ring proof parameters. /// -/// Wraps [`PcsParams`] and [`PiopParams`]. +/// Contains the cryptographic parameters needed for ring proof generation and verification: +/// - `pcs`: Polynomial Commitment Scheme parameters (KZG setup) +/// - `piop`: Polynomial Interactive Oracle Proof parameters #[derive(Clone)] pub struct RingProofParams where @@ -243,19 +313,18 @@ where CurveConfig: TECurveConfig + Clone, AffinePoint: TEMapping>, { - /// Construct new ring proof params suitable for the given ring size. + /// Construct deterministic ring proof params for the given ring size. /// - /// Calls into [`RingProofParams::from_rand`] with a `ChaCha20Rng` seeded with `seed`. + /// Creates parameters using a deterministic `ChaCha20Rng` seeded with `seed`. pub fn from_seed(ring_size: usize, seed: [u8; 32]) -> Self { use ark_std::rand::SeedableRng; let mut rng = rand_chacha::ChaCha20Rng::from_seed(seed); Self::from_rand(ring_size, &mut rng) } - /// Construct a new random ring context suitable for the given ring size. + /// Construct random ring proof params for the given ring size. /// - /// Calls into [`RingProofParams::from_srs`] with randomly generated [`PcsParams`] - /// large enough to be used for the given `ring_size`. + /// Generates a new KZG setup with sufficient degree to support the specified ring size. pub fn from_rand(ring_size: usize, rng: &mut impl ark_std::rand::RngCore) -> Self { use ring_proof::pcs::PCS; let max_degree = pcs_domain_size::(ring_size) - 1; @@ -263,18 +332,19 @@ where Self::from_pcs_params(ring_size, pcs_params).expect("PCS params is correct") } - /// Construct a new random ring context suitable for the given [`PcsParams`]. + /// Construct ring proof params from existing KZG setup. /// - /// Fails if the domain representable via the supplied `PcsParams` is not sufficiently - /// large for the given `ring_size`. + /// Creates parameters using an existing KZG setup, truncating if larger than needed + /// or returning an error if the setup is insufficient for the specified ring size. /// - /// If the domain size of `PcsParams` exceeds the required limit, the extra items are truncated. + /// * `ring_size` - Maximum number of keys in the ring + /// * `pcs_params` - KZG setup parameters pub fn from_pcs_params(ring_size: usize, mut pcs_params: PcsParams) -> Result { let pcs_domain_size = pcs_domain_size::(ring_size); if pcs_params.powers_in_g1.len() < pcs_domain_size || pcs_params.powers_in_g2.len() < 2 { return Err(Error::InvalidData); } - // Keep only the required powers of tau. + // Keep only the required powers of tau pcs_params.powers_in_g1.truncate(pcs_domain_size); pcs_params.powers_in_g2.truncate(2); let piop_domain_size = piop_domain_size::(ring_size); @@ -290,18 +360,21 @@ where self.piop.keyset_part_size } - /// Construct [`RingProverKey`] for the given ring. + /// Create a prover key for the given ring of public keys. + /// + /// Indexes the ring and prepares the cryptographic material needed for proving. + /// If the ring exceeds the maximum supported size, excess keys are ignored. /// - /// Note: if `pks.len() > self.max_ring_size()` the extra keys in the tail are ignored. + /// * `pks` - Array of public keys forming the ring pub fn prover_key(&self, pks: &[AffinePoint]) -> RingProverKey { let pks = TEMapping::to_te_slice(&pks[..pks.len().min(self.max_ring_size())]); ring_proof::index(&self.pcs, &self.piop, &pks).0 } - /// Construct [`RingProver`] from [`RingProverKey`] for the prover implied by `key_index`. + /// Create a prover instance for a specific position in the ring. /// - /// Key index is the prover index within the `pks` sequence passed to construct the - /// [`RingProverKey`] via the `prover_key` method. + /// * `prover_key` - Ring prover key created with `prover_key()` + /// * `key_index` - Position of the prover's public key in the original ring pub fn prover(&self, prover_key: RingProverKey, key_index: usize) -> RingProver { RingProver::::init( prover_key, @@ -311,20 +384,23 @@ where ) } - /// Construct a `RingVerifierKey` instance for the given ring. + /// Create a verifier key for the given ring of public keys. + /// + /// Indexes the ring and prepares the cryptographic material needed for verification. + /// If the ring exceeds the maximum supported size, excess keys are ignored. /// - /// Note: if `pks.len() > self.max_ring_size()` the extra keys in the tail are ignored. + /// * `pks` - Array of public keys forming the ring pub fn verifier_key(&self, pks: &[AffinePoint]) -> RingVerifierKey { let pks = TEMapping::to_te_slice(&pks[..pks.len().min(self.max_ring_size())]); ring_proof::index(&self.pcs, &self.piop, &pks).1 } - /// Construct `RingVerifierKey` instance for the ring previously committed. + /// Create a verifier key from a precomputed ring commitment. /// - /// The `RingCommitment` instance can be obtained via the `VerifierKey::commitment()` method. + /// Allows efficient reconstruction of a verifier key without needing the full ring. + /// The commitment can be obtained from an existing verifier key via `commitment()`. /// - /// This allows to quickly reconstruct the verifier key without having to recompute the - /// keys commitment. + /// * `commitment` - Precomputed commitment to the ring of public keys pub fn verifier_key_from_commitment( &self, commitment: RingCommitment, @@ -333,10 +409,10 @@ where RingVerifierKey::::from_commitment_and_kzg_vk(commitment, self.pcs.raw_vk()) } - /// Builder for incremental construction of the verifier key. + /// Create a builder for incremental construction of the verifier key. /// - /// This also returns a `RingBuilderPcsParams` which may be used to append new key items - /// to the `RingVerifierKeyBuilder` instance its tne `SrsLookup` implementation. + /// Returns a builder and associated PCS parameters that can be used to + /// construct a verifier key by adding public keys in batches. pub fn verifier_key_builder(&self) -> (RingVerifierKeyBuilder, RingBuilderPcsParams) { type RingBuilderKey = ring_proof::ring::RingBuilderKey, ::Pairing>; @@ -347,7 +423,9 @@ where (builder, builder_pcs_params) } - /// Construct `RingVerifier` from `RingVerifierKey`. + /// Create a verifier instance from a verifier key. + /// + /// * `verifier_key` - Ring verifier key created with `verifier_key()` pub fn verifier(&self, verifier_key: RingVerifierKey) -> RingVerifier { RingVerifier::::init( verifier_key, @@ -356,13 +434,14 @@ where ) } - /// Constructs a `RingVerifier` from `RingVerifierKey` without no `RingProofParams`. + /// Create a verifier instance without requiring the full parameters. + /// + /// Creates a verifier using only the verifier key and ring size, computing + /// necessary parameters on-the-fly. This is more memory efficient but slightly + /// less computationally efficient than using the full parameters. /// - /// While this approach is slightly less efficient than using pre-constructed `RingProofParams`, - /// as some parameters need to be computed on-the-fly, it is beneficial in memory or - /// storage constrained environments. This avoids the need to retain the full `RingProofParams` for - /// ring signature verification. Instead, the `VerifierKey` contains only the essential information - /// needed to verify ring proofs. + /// * `verifier_key` - Ring verifier key + /// * `ring_size` - Size of the ring used to create the verifier key pub fn verifier_no_context( verifier_key: RingVerifierKey, ring_size: usize, @@ -455,7 +534,10 @@ type PartialRingCommitment = type RawVerifierKey = as ring_proof::pcs::PcsParams>::RVK; -/// Ring verifier key builder. +/// Builder for incremental construction of ring verifier keys. +/// +/// Allows constructing a verifier key by adding public keys in batches, +/// which is useful for large rings or memory-constrained environments. #[derive(Clone, CanonicalSerialize, CanonicalDeserialize)] pub struct RingVerifierKeyBuilder where @@ -470,7 +552,9 @@ where pub type G1Affine = <::Pairing as Pairing>::G1Affine; pub type G2Affine = <::Pairing as Pairing>::G2Affine; -/// Lagrangian form SRS entries lookup. +/// Trait for accessing Structured Reference String entries in Lagrangian basis. +/// +/// Provides access to precomputed SRS elements needed for efficient ring operations. pub trait SrsLookup where BaseField: ark_ff::PrimeField, @@ -512,7 +596,10 @@ where CurveConfig: TECurveConfig + Clone, AffinePoint: TEMapping>, { - /// Construct an empty ring verifier key builder. + /// Create a new empty ring verifier key builder. + /// + /// * `params` - Ring proof parameters + /// * `lookup` - SRS lookup implementation for accessing precomputed values pub fn new(params: &RingProofParams, lookup: impl SrsLookup) -> Self { use ring_proof::pcs::PcsParams; let lookup = |range: Range| lookup.lookup(range).ok_or(()); @@ -522,21 +609,19 @@ where RingVerifierKeyBuilder { partial, raw_vk } } - /// Free public key slots. + /// Get the number of remaining slots available in the ring. #[inline(always)] pub fn free_slots(&self) -> usize { self.partial.max_keys - self.partial.curr_keys } - /// Append a new member to the ring verifier key. + /// Add public keys to the ring being built. /// - /// If the `pks` length is greater than the number of available slots in the ring - /// then an error is returned with the available slots count. + /// * `pks` - Public keys to add to the ring + /// * `lookup` - SRS lookup implementation for accessing precomputed values /// - /// If the available free slots are not sufficient to append `pks` sequence, the - /// number of available slots are returned in the error variant. - /// If the supplied `lookup` returns `None`, then an error with `usize::MAX` is - /// returned. + /// Returns `Ok(())` if keys were added successfully, or `Err(available_slots)` + /// if there's not enough space. Returns `Err(usize::MAX)` if SRS lookup fails. pub fn append( &mut self, pks: &[AffinePoint], @@ -560,7 +645,7 @@ where Ok(()) } - /// Build verifier key. + /// Complete the building process and create the verifier key. pub fn finalize(self) -> RingVerifierKey { RingVerifierKey::::from_ring_and_kzg_vk(&self.partial, self.raw_vk) } diff --git a/src/suites/baby_jubjub.rs b/src/suites/baby_jubjub.rs index 908e2d4..565d2dd 100644 --- a/src/suites/baby_jubjub.rs +++ b/src/suites/baby_jubjub.rs @@ -1,4 +1,4 @@ -//! `ECVRF Baby-JubJub SHA-512 Try and Increment H2C` suite. +//! ECVRF Baby-JubJub SHA-512 TAI suite //! //! Configuration: //! diff --git a/src/suites/bandersnatch.rs b/src/suites/bandersnatch.rs index 62f2865..9427a93 100644 --- a/src/suites/bandersnatch.rs +++ b/src/suites/bandersnatch.rs @@ -1,4 +1,4 @@ -//! `ECVRF Bandersnatch SHA-512 Elligator2` suite. +//! # ECVRF Bandersnatch SHA-512 Elligator2 suite //! //! Configuration: //! diff --git a/src/suites/ed25519.rs b/src/suites/ed25519.rs index 09d1dbd..c074b7a 100644 --- a/src/suites/ed25519.rs +++ b/src/suites/ed25519.rs @@ -1,4 +1,4 @@ -//! `ECVRF-EDWARDS25519-SHA-512-TAI` suite. +//! # ECVRF Ed25519 SHA-512 TAI suite //! //! Configuration (RFC-9381 with some compromises): //! diff --git a/src/suites/jubjub.rs b/src/suites/jubjub.rs index 010128b..fdf00e2 100644 --- a/src/suites/jubjub.rs +++ b/src/suites/jubjub.rs @@ -1,4 +1,4 @@ -//! `ECVRF JubJub SHA-512 Try and Increment H2C` suite. +//! # ECVRF JubJub SHA-512 TAI suite //! //! Configuration: //! diff --git a/src/suites/mod.rs b/src/suites/mod.rs index 55bbead..af2dbe8 100644 --- a/src/suites/mod.rs +++ b/src/suites/mod.rs @@ -1,6 +1,26 @@ -//! Featured suites. +//! # Cipher Suites //! -//! Each is conditionally compiled based on its corresponding feature flag. +//! This module provides pre-configured cipher suites for various elliptic curves. +//! Each suite is conditionally compiled based on its corresponding feature flag. +//! +//! ## Available Suites +//! +//! - **Ed25519**: Edwards curve with SHA-512 hash function and Try-And-Increment (TAI) +//! hash-to-curve method. Supports IETF and Pedersen VRF schemes. +//! +//! - **Secp256r1**: NIST P-256 curve with SHA-256 hash function and TAI hash-to-curve +//! method. Supports IETF and Pedersen VRF schemes. Uses SEC1 point encoding. +//! +//! - **Bandersnatch**: Edwards curve defined over the BLS12-381 scalar field with +//! SHA-512 hash function. Supports IETF, Pedersen, and Ring VRF schemes. +//! Available in both Edwards and Short Weierstrass forms. +//! +//! - **JubJub**: Edwards curve defined over the BLS12-381 scalar field with +//! SHA-512 hash function. Supports IETF, Pedersen, and Ring VRF schemes. +//! +//! - **Baby-JubJub**: Edwards curve defined over the BN254 scalar field with +//! SHA-512 hash function. Supports IETF, Pedersen, and Ring VRF schemes. +//! Optimized for Ethereum compatibility. #[cfg(test)] pub(crate) mod testing; diff --git a/src/suites/secp256r1.rs b/src/suites/secp256r1.rs index 907b7df..bfaf1ca 100644 --- a/src/suites/secp256r1.rs +++ b/src/suites/secp256r1.rs @@ -1,4 +1,4 @@ -//! `ECVRF-P256-SHA256-TAI` suite. +//! # ECVRF P256 SHA-256 TAI suite //! //! Configuration (RFC-9381): //! diff --git a/src/utils/common.rs b/src/utils/common.rs index a4efc5d..913721e 100644 --- a/src/utils/common.rs +++ b/src/utils/common.rs @@ -1,3 +1,9 @@ +//! Common cryptographic utility functions. +//! +//! This module provides implementations of various cryptographic operations +//! used throughout the VRF schemes, including hashing, challenge generation, +//! and hash-to-curve algorithms. + use crate::*; use ark_ec::{ AffineRepr, @@ -9,12 +15,17 @@ use digest::{Digest, FixedOutputReset}; #[cfg(not(feature = "std"))] use ark_std::vec::Vec; -// Generic hash wrapper. +/// Generic hash wrapper. +/// +/// Computes a hash of the provided data using the specified hash function. pub fn hash(data: &[u8]) -> digest::Output { H::new().chain_update(data).finalize() } /// Generic HMAC wrapper. +/// +/// Computes an HMAC of the provided data using the specified key and hash function. +/// Used for deterministic nonce generation in RFC-6979. #[cfg(feature = "rfc-6979")] fn hmac(sk: &[u8], data: &[u8]) -> Vec { use hmac::{Mac, SimpleHmac}; @@ -29,7 +40,8 @@ fn hmac(sk: &[u8], data: &[u8]) -> /// Try-And-Increment (TAI) method as defined by RFC 9381 section 5.4.1.1. /// /// Implements ECVRF_encode_to_curve in a simple and generic way that works -/// for any elliptic curve. +/// for any elliptic curve. This method iteratively attempts to hash the input +/// with an incrementing counter until a valid curve point is found. /// /// To use this algorithm, hash length MUST be at least equal to the field length. /// @@ -39,6 +51,15 @@ fn hmac(sk: &[u8], data: &[u8]) -> /// /// May systematically fail if `Suite::Hasher` output is not sufficient to /// construct a point according to the `Suite::Codec` in use. +/// +/// # Parameters +/// +/// * `data` - The input data to hash to a curve point +/// +/// # Returns +/// +/// * `Some(AffinePoint)` - A valid curve point in the prime-order subgroup +/// * `None` - If no valid point could be found after 256 attempts pub fn hash_to_curve_tai_rfc_9381(data: &[u8]) -> Option> { use ark_ec::AffineRepr; @@ -64,10 +85,22 @@ pub fn hash_to_curve_tai_rfc_9381(data: &[u8]) -> Option)` - A valid curve point in the prime-order subgroup +/// * `None` - If the hash-to-curve operation fails #[allow(unused)] pub fn hash_to_curve_ell2_rfc_9380( data: &[u8], @@ -96,6 +129,24 @@ where } /// Challenge generation according to RFC-9381 section 5.4.3. +/// +/// Generates a challenge scalar by hashing a sequence of curve points and additional data. +/// This is used in the Schnorr-like signature scheme for VRF proofs. +/// +/// The function follows the procedure specified in RFC-9381: +/// 1. Start with a domain separator and suite ID +/// 2. Append the encoded form of each provided point +/// 3. Append the additional data +/// 4. Hash the result and interpret it as a scalar +/// +/// # Parameters +/// +/// * `pts` - Array of curve points to include in the challenge +/// * `ad` - Additional data to bind to the challenge +/// +/// # Returns +/// +/// A scalar field element derived from the hash of the inputs pub fn challenge_rfc_9381(pts: &[&AffinePoint], ad: &[u8]) -> ScalarField { const DOM_SEP_START: u8 = 0x02; const DOM_SEP_END: u8 = 0x00; @@ -111,6 +162,9 @@ pub fn challenge_rfc_9381(pts: &[&AffinePoint], ad: &[u8]) -> Scala /// Point to a hash according to RFC-9381 section 5.2. /// +/// Converts an elliptic curve point to a hash value, following the procedure in RFC-9381. +/// This is used to derive the final VRF output bytes from the VRF output point. +/// /// According to the RFC, the input point `pt` should be multiplied by the cofactor /// before being hashed. However, in typical usage, the hashed point is the result /// of a scalar multiplication on a point produced by the `Suite::data_to_point` @@ -123,9 +177,14 @@ pub fn challenge_rfc_9381(pts: &[&AffinePoint], ad: &[u8]) -> Scala /// purpose of multiplying by the cofactor is as a safeguard against potential issues /// with an incorrect implementation of `data_to_point`. /// -/// Since multiplying by the cofactor changes the point being hashed, this step is -/// made optional to accommodate scenarios where strict compliance with the RFC's -/// prescribed procedure is not required. +/// # Parameters +/// +/// * `pt` - The elliptic curve point to hash +/// * `mul_by_cofactor` - Whether to multiply the point by the cofactor before hashing +/// +/// # Returns +/// +/// A hash value derived from the encoded point pub fn point_to_hash_rfc_9381( pt: &AffinePoint, mul_by_cofactor: bool, @@ -146,9 +205,20 @@ pub fn point_to_hash_rfc_9381( /// Nonce generation according to RFC-9381 section 5.4.2.2. /// /// This procedure is based on section 5.1.6 of RFC 8032: "Edwards-Curve Digital -/// Signature Algorithm (EdDSA)". +/// Signature Algorithm (EdDSA)". It generates a deterministic nonce by hashing +/// the secret key and input point together. +/// +/// The deterministic generation ensures that the same nonce is never used twice +/// with the same secret key for different inputs, which is critical for security. /// -/// The algorithm generate the nonce value in a deterministic pseudorandom fashion. +/// # Parameters +/// +/// * `sk` - The secret scalar key +/// * `input` - The input point +/// +/// # Returns +/// +/// A scalar field element to be used as a nonce /// /// # Panics /// @@ -175,7 +245,17 @@ pub fn nonce_rfc_8032(sk: &ScalarField, input: &AffinePoint) -> /// the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature /// Algorithm (ECDSA)". /// -/// The algorithm generate the nonce value in a deterministic pseudorandom fashion. +/// It generates a deterministic nonce using HMAC-based extraction, which provides +/// strong security guarantees against nonce reuse or biased nonce generation. +/// +/// # Parameters +/// +/// * `sk` - The secret scalar key +/// * `input` - The input point +/// +/// # Returns +/// +/// A scalar field element to be used as a nonce #[cfg(feature = "rfc-6979")] pub fn nonce_rfc_6979(sk: &ScalarField, input: &AffinePoint) -> ScalarField where diff --git a/src/utils/mod.rs b/src/utils/mod.rs index cbd8bc7..29a639e 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,20 +1,31 @@ -//! Common utilities +//! # Common utilities +//! +//! This module provides cryptographic utility functions and curve mappings used +//! throughout the VRF implementations. pub mod common; pub mod te_sw_map; -/// Standard procedures. +/// Standard cryptographic procedures. +/// +/// Includes hash functions, challenge generation, and point-to-hash conversions +/// following RFC-9381 and other standards. pub use common::*; -/// Twisted Edwards to Short Weierstrass mapping. + +/// Twisted Edwards to Short Weierstrass curve mapping. +/// +/// Provides bidirectional mappings between different curve representations, +/// allowing operations to be performed in the most convenient form. pub use te_sw_map::*; /// Point scalar multiplication with optional secret splitting. /// -/// Secret scalar split into the sum of two scalars, which randomly mutate but -/// retain the same sum. Incurs 2x penalty in scalar multiplications, but provides -/// side channel defenses. +/// When the `secret-split` feature is enabled, this macro splits the secret scalar +/// into the sum of two randomly generated scalars that retain the same sum. This +/// technique provides side-channel resistance at the cost of doubling the number +/// of scalar multiplications. /// -/// Note: actual secret splitting is enabled via the `secret-split` feature. +/// Without the feature enabled, it performs a standard scalar multiplication. mod secret_split { #[cfg(feature = "secret-split")] #[doc(hidden)] diff --git a/src/utils/te_sw_map.rs b/src/utils/te_sw_map.rs index 81c7946..d9841d2 100644 --- a/src/utils/te_sw_map.rs +++ b/src/utils/te_sw_map.rs @@ -1,3 +1,8 @@ +//! # Twisted Edwards to Short Weierstrass curve mapping utilities. +//! +//! This module provides bidirectional mappings between different curve representations, +//! allowing operations to be performed in the most convenient form for a given task. + use ark_ec::{ CurveConfig, short_weierstrass::{Affine as SWAffine, SWCurveConfig}, @@ -6,13 +11,23 @@ use ark_ec::{ use ark_ff::{Field, One}; use ark_std::borrow::Cow; -// Constants used in mapping TE form to SW form and vice versa +/// Constants used in mapping TE form to SW form and vice versa. +/// Configuration trait for curves that support mapping between representations. +/// +/// This trait must be implemented for curves that need to be converted between +/// Twisted Edwards, Short Weierstrass, and Montgomery forms. pub trait MapConfig: TECurveConfig + SWCurveConfig + MontCurveConfig { + /// Precomputed value of Montgomery curve parameter A divided by 3. const MONT_A_OVER_THREE: ::BaseField; + + /// Precomputed inverse of Montgomery curve parameter B. const MONT_B_INV: ::BaseField; } -/// Map a a point in Short Weierstrass form into its corresponding point in Twisted Edwards form. +/// Map a point in Short Weierstrass form into its corresponding point in Twisted Edwards form. +/// +/// This function performs the conversion by first mapping from Short Weierstrass to Montgomery form, +/// then from Montgomery to Twisted Edwards form. pub fn sw_to_te(point: &SWAffine) -> Option> { // First map the point from SW to Montgomery // (Bx - A/3, By) @@ -30,7 +45,10 @@ pub fn sw_to_te(point: &SWAffine) -> Option> { Some(TEAffine::new_unchecked(v, w)) } -/// Map a a point in Twisted Edwards form into its corresponding point in Short Weierstrass form. +/// Map a point in Twisted Edwards form into its corresponding point in Short Weierstrass form. +/// +/// This function performs the conversion by first mapping from Twisted Edwards to Montgomery form, +/// then from Montgomery to Short Weierstrass form. pub fn te_to_sw(point: &TEAffine) -> Option> { // Map from TE to Montgomery: (1+y)/(1-y), (1+y)/(x(1-y)) let v_denom = <::BaseField as One>::one() - point.y; @@ -48,11 +66,21 @@ pub fn te_to_sw(point: &TEAffine) -> Option> { Some(SWAffine::new_unchecked(x, y)) } +/// Trait for types that can be converted from/to Short Weierstrass form. +/// +/// This trait provides methods to convert between a type and its Short Weierstrass representation, +/// both for individual points and slices of points. pub trait SWMapping { + /// Convert a Short Weierstrass point to this type. fn from_sw(sw: SWAffine) -> Self; + /// Convert this type to a Short Weierstrass point. fn into_sw(self) -> SWAffine; + /// Convert a slice of this type to a slice of Short Weierstrass points. + /// + /// Returns a borrowed slice if no conversion is needed, or an owned + /// vector if conversion is required. fn to_sw_slice(slice: &[Self]) -> Cow<[SWAffine]> where Self: Sized; @@ -102,11 +130,21 @@ impl SWMapping for TEAffine { } } +/// Trait for types that can be converted from/to Twisted Edwards form. +/// +/// This trait provides methods to convert between a type and its Twisted Edwards representation, +/// both for individual points and slices of points. pub trait TEMapping { + /// Convert a Twisted Edwards point to this type. fn from_te(te: TEAffine) -> Self; + /// Convert this type to a Twisted Edwards point. fn into_te(self) -> TEAffine; + /// Convert a slice of this type to a slice of Twisted Edwards points. + /// + /// Returns a borrowed slice if no conversion is needed, or an owned + /// vector if conversion is required. fn to_te_slice(slice: &[Self]) -> Cow<[TEAffine]> where Self: Sized;