From 3672afae77f37cc411f4c81ad8049e95fe71238f Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 24 Jun 2022 17:22:52 -0400 Subject: [PATCH 1/7] fix: simplify algebra APIs --- manta-accounting/src/key.rs | 2 +- manta-accounting/src/transfer/mod.rs | 35 +- manta-crypto/src/algebra.rs | 224 +++++++++++ manta-crypto/src/ecc.rs | 368 ------------------ manta-crypto/src/encryption/hybrid.rs | 38 +- manta-crypto/src/key.rs | 367 ++++++----------- manta-crypto/src/lib.rs | 2 +- manta-pay/src/bin/measure.rs | 4 +- manta-pay/src/config.rs | 24 +- .../src/crypto/constraint/arkworks/mod.rs | 16 + manta-pay/src/crypto/ecc/arkworks.rs | 191 +++------ manta-pay/src/crypto/key.rs | 2 +- manta-pay/src/signer/base.rs | 4 +- 13 files changed, 472 insertions(+), 805 deletions(-) create mode 100644 manta-crypto/src/algebra.rs delete mode 100644 manta-crypto/src/ecc.rs diff --git a/manta-accounting/src/key.rs b/manta-accounting/src/key.rs index ab87bf006..80d3df6ac 100644 --- a/manta-accounting/src/key.rs +++ b/manta-accounting/src/key.rs @@ -32,7 +32,7 @@ use core::{ marker::PhantomData, }; use manta_crypto::{ - key::KeyDerivationFunction, + key::kdf::KeyDerivationFunction, rand::{CryptoRng, RngCore, Sample}, }; diff --git a/manta-accounting/src/transfer/mod.rs b/manta-accounting/src/transfer/mod.rs index eafc9330c..aa6376301 100644 --- a/manta-accounting/src/transfer/mod.rs +++ b/manta-accounting/src/transfer/mod.rs @@ -39,7 +39,7 @@ use manta_crypto::{ ProofSystemInput, Public, Secret, Variable, }, encryption::hybrid::{DecryptedMessage, EncryptedMessage, HybridPublicKeyEncryptionScheme}, - key::{KeyAgreementScheme, KeyDerivationFunction}, + key::{self, agreement::Derive}, rand::{CryptoRng, RngCore, Sample}, }; use manta_util::SizeLimit; @@ -116,10 +116,9 @@ pub trait Configuration { type PublicKey: Clone; /// Key Agreement Scheme Type - type KeyAgreementScheme: KeyAgreementScheme< - SecretKey = SecretKey, - PublicKey = PublicKey, - >; + type KeyAgreementScheme: key::agreement::Types, PublicKey = PublicKey> + + key::agreement::Agree + + key::agreement::Derive; /// Secret Key Variable Type type SecretKeyVar: Variable>; @@ -129,11 +128,10 @@ pub trait Configuration { + constraint::PartialEq; /// Key Agreement Scheme Variable Type - type KeyAgreementSchemeVar: KeyAgreementScheme< - Self::Compiler, - SecretKey = SecretKeyVar, - PublicKey = PublicKeyVar, - > + Constant; + type KeyAgreementSchemeVar: Constant + + key::agreement::Types, PublicKey = PublicKeyVar> + + key::agreement::Agree + + key::agreement::Derive; /// Unspent Transaction Output Type type Utxo: PartialEq; @@ -152,13 +150,14 @@ pub trait Configuration { + constraint::PartialEq; /// UTXO Commitment Scheme Variable Type - type UtxoCommitmentSchemeVar: UtxoCommitmentScheme< + type UtxoCommitmentSchemeVar: Constant + + UtxoCommitmentScheme< Self::Compiler, EphemeralSecretKey = SecretKeyVar, PublicSpendKey = PublicKeyVar, Asset = AssetVar, Utxo = UtxoVar, - > + Constant; + >; /// Void Number Type type VoidNumber: PartialEq; @@ -175,12 +174,13 @@ pub trait Configuration { + constraint::PartialEq; /// Void Number Commitment Scheme Variable Type - type VoidNumberCommitmentSchemeVar: VoidNumberCommitmentScheme< + type VoidNumberCommitmentSchemeVar: Constant + + VoidNumberCommitmentScheme< Self::Compiler, SecretSpendKey = SecretKeyVar, Utxo = UtxoVar, VoidNumber = VoidNumberVar, - > + Constant; + >; /// UTXO Accumulator Model Type type UtxoAccumulatorModel: Model; @@ -200,14 +200,15 @@ pub trait Configuration { >; /// UTXO Accumulator Model Variable Type - type UtxoAccumulatorModelVar: AssertValidVerification + type UtxoAccumulatorModelVar: Constant + + AssertValidVerification + Model< Self::Compiler, Item = Self::UtxoVar, Witness = Self::UtxoAccumulatorWitnessVar, Output = Self::UtxoAccumulatorOutputVar, Verification = Bool, - > + Constant; + >; /// Asset Id Variable Type type AssetIdVar: Variable @@ -400,7 +401,7 @@ where pub fn derive_owned(&self, secret_key: SecretKey) -> PublicKey { self.note_encryption_scheme .key_agreement_scheme() - .derive_owned(secret_key, &mut ()) + .derive(&secret_key, &mut ()) } /// Computes the [`Utxo`] associated to `ephemeral_secret_key`, `public_spend_key`, and `asset`. diff --git a/manta-crypto/src/algebra.rs b/manta-crypto/src/algebra.rs new file mode 100644 index 000000000..a60c38431 --- /dev/null +++ b/manta-crypto/src/algebra.rs @@ -0,0 +1,224 @@ +// Copyright 2019-2022 Manta Network. +// This file is part of manta-rs. +// +// manta-rs is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// manta-rs is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with manta-rs. If not, see . + +//! Algebraic Constructions + +use crate::{ + eclair::alloc::Constant, + key, + rand::{CryptoRng, RngCore, Sample}, +}; +use core::marker::PhantomData; +use manta_util::codec::{Decode, DecodeError, Encode, Read, Write}; + +#[cfg(feature = "serde")] +use manta_util::serde::{Deserialize, Serialize}; + +/// Ring of Scalars +pub trait Scalar { + /// Adds `rhs` to `self` in the ring. + fn add(&self, rhs: &Self, compiler: &mut COM) -> Self; + + /// Multiplies `self` by `rhs` in the ring. + fn mul(&self, rhs: &Self, compiler: &mut COM) -> Self; +} + +/// Group +pub trait Group { + /// Ring of Scalars + type Scalar: Scalar; + + /// Adds `rhs` to `self` in the group. + fn add(&self, rhs: &Self, compiler: &mut COM) -> Self; + + /// Multiplies `self` by `scalar` in the group. + fn mul(&self, scalar: &Self::Scalar, compiler: &mut COM) -> Self; +} + +/// Diffie-Hellman Key Agreement Scheme +#[cfg_attr( + feature = "serde", + derive(Deserialize, Serialize), + serde(crate = "manta_util::serde", deny_unknown_fields) +)] +#[derive(derivative::Derivative)] +#[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct DiffieHellman { + /// Group Generator + pub generator: G, + + /// Type Parameter Marker + __: PhantomData, +} + +impl DiffieHellman { + /// Builds a new [`DiffieHellman`] key agreement scheme from the given `generator`. + #[inline] + pub fn new(generator: G) -> Self { + Self { + generator, + __: PhantomData, + } + } + + /// Converts `self` into the group generator. + #[inline] + pub fn into_inner(self) -> G { + self.generator + } +} + +impl Constant for DiffieHellman +where + G: Constant, +{ + type Type = DiffieHellman; + + #[inline] + fn new_constant(value: &Self::Type, compiler: &mut COM) -> Self { + Self::new(G::new_constant(&value.generator, compiler)) + } +} + +impl key::agreement::Types for DiffieHellman +where + G: Group + security::ComputationalDiffieHellmanHardness, +{ + type SecretKey = G::Scalar; + type PublicKey = G; + type SharedSecret = G; +} + +impl key::agreement::Derive for DiffieHellman +where + G: Group + security::ComputationalDiffieHellmanHardness, +{ + #[inline] + fn derive(&self, secret_key: &Self::SecretKey, compiler: &mut COM) -> Self::PublicKey { + self.generator.mul(secret_key, compiler) + } +} + +impl key::agreement::Agree for DiffieHellman +where + G: Group + security::ComputationalDiffieHellmanHardness, +{ + #[inline] + fn agree( + &self, + public_key: &Self::PublicKey, + secret_key: &Self::SecretKey, + compiler: &mut COM, + ) -> Self::SharedSecret { + public_key.mul(secret_key, compiler) + } +} + +impl Decode for DiffieHellman +where + G: Decode, +{ + type Error = G::Error; + + #[inline] + fn decode(mut reader: R) -> Result> + where + R: Read, + { + Ok(Self::new(G::decode(&mut reader)?)) + } +} + +impl Encode for DiffieHellman +where + G: Encode, +{ + #[inline] + fn encode(&self, mut writer: W) -> Result<(), W::Error> + where + W: Write, + { + self.generator.encode(&mut writer)?; + Ok(()) + } +} + +impl Sample for DiffieHellman +where + G: Sample, +{ + #[inline] + fn sample(distribution: D, rng: &mut R) -> Self + where + R: CryptoRng + RngCore + ?Sized, + { + Self::new(G::sample(distribution, rng)) + } +} + +/// Security Assumptions +/// +/// The following outlines some standard security assumptions for cryptographic protocols built on +/// [`Group`] types. These security properties can be attached to instances of [`Group`] which we +/// assume to have these hardness properties. +pub mod security { + /// Discrete Logarithm Hardness Assumption + /// + /// For a [`Group`](super::Group) `G`, it should be infeasible to find a procedure `f` that + /// makes this function return `true`: + /// + /// ```text + /// fn solve(g: G, y: G, f: F) -> bool + /// where + /// F: FnOnce(G, G) -> G::Scalar, + /// { + /// y == g.mul(f(g, y)) + /// } + /// ``` + pub trait DiscreteLogarithmHardness {} + + /// Computational Diffie-Hellman Hardness Assumption + /// + /// For a [`Group`](super::Group) `G`, it should be infeasible to find a procedure `f` that + /// makes this function return `true`: + /// + /// ```text + /// fn solve(g: G, a: G::Scalar, b: G::Scalar, f: F) -> bool + /// where + /// F: FnOnce(G, G, G) -> G, + /// { + /// f(g, g.mul(a), g.mul(b)) == g.mul(a.mul(b)) + /// } + /// ``` + pub trait ComputationalDiffieHellmanHardness: DiscreteLogarithmHardness {} + + /// Decisional Diffie-Hellman Hardness Assumption + /// + /// For a [`Group`](super::Group) `G`, it should be infeasible to distinguish the probability + /// distributions over the following two functions when [`G::Scalar](super::Group::Scalar) + /// inputs are sampled uniformly from their domain (and `g` the generator is fixed): + /// + /// ```text + /// fn dh_triple(g: G, a: G::Scalar, b: G::Scalar) -> (G, G, G) { + /// (g.mul(a), g.mul(b), g.mul(a.mul(b))) + /// } + /// + /// fn random_triple(g: G, a: G::Scalar, b: G::Scalar, c: G::Scalar) -> (G, G, G) { + /// (g.mul(a), g.mul(b), g.mul(c)) + /// } + /// ``` + pub trait DecisionalDiffieHellmanHardness: ComputationalDiffieHellmanHardness {} +} diff --git a/manta-crypto/src/ecc.rs b/manta-crypto/src/ecc.rs deleted file mode 100644 index 30badd2c6..000000000 --- a/manta-crypto/src/ecc.rs +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright 2019-2022 Manta Network. -// This file is part of manta-rs. -// -// manta-rs is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// manta-rs is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with manta-rs. If not, see . - -//! Elliptic Curve Cryptography - -// TODO: Make sure we can use `PreprocessedScalarMulTable` as a drop-in replacement for `G`. - -use crate::{ - constraint::Constant, - key::{KeyAgreementScheme, KeyDerivationFunction}, - rand::{CryptoRng, RngCore, Sample}, -}; -use alloc::{boxed::Box, vec::Vec}; -use manta_util::{ - codec::{Decode, DecodeError, Encode, Read, Write}, - BoxArray, -}; - -#[cfg(feature = "serde")] -use manta_util::serde::{Deserialize, Serialize}; - -/// Elliptic Curve Point Doubling Operation -pub trait PointDouble { - /// Output Type - type Output; - - /// Performs a point doubling of `self` in `compiler`. - #[must_use] - fn double(&self, compiler: &mut COM) -> Self::Output; - - /// Performs a point doubling of `self` in `compiler` using an owned value. - /// - /// # Implementation Note - /// - /// This method is an optimization path for [`double`](Self::double) whenever operating with - /// owned values is more efficient than with shared references. - #[inline] - fn double_owned(self, compiler: &mut COM) -> Self::Output - where - Self: Sized, - { - self.double(compiler) - } - - /// Performs a point doubling of `self` in `compiler`, modifying `self` in-place. - #[inline] - fn double_assign(&mut self, compiler: &mut COM) - where - Self: PointDouble + Sized, - { - *self = self.double(compiler); - } -} - -/// Elliptic Curve Point Addition Operation -pub trait PointAdd { - /// Output Type - type Output; - - /// Adds `rhs` to `self` in `compiler`, returning a new group element. - #[must_use] - fn add(&self, rhs: &Self, compiler: &mut COM) -> Self::Output; - - /// Adds an owned `rhs` value to `self` in `compiler`, returning a new group element. - /// - /// # Implementation Note - /// - /// This method is an optimization path for [`add`](Self::add) whenever operating with owned - /// values is more efficient than with shared references. - #[inline] - fn add_owned(self, rhs: Self, compiler: &mut COM) -> Self::Output - where - Self: Sized, - { - self.add(&rhs, compiler) - } - - /// Adds `rhs` to `self` in `compiler`, modifying `self` in-place. - #[inline] - fn add_assign(&mut self, rhs: &Self, compiler: &mut COM) - where - Self: PointAdd + Sized, - { - *self = self.add(rhs, compiler); - } -} - -/// Elliptic Curve Scalar Multiplication Operation -pub trait ScalarMul { - /// Scalar Field - type Scalar; - - /// Output Type - type Output; - - /// Multiplies `self` by `scalar` in `compiler`, returning a new group element. - #[must_use] - fn scalar_mul(&self, scalar: &Self::Scalar, compiler: &mut COM) -> Self::Output; - - /// Multiplies an owned `scalar` value to `self` in `compiler`, returning a new group element. - /// - /// # Implementation Note - /// - /// This method is an optimization path for [`scalar_mul`](Self::scalar_mul) whenever operating - /// with owned values is more efficient than with shared references. - #[inline] - fn scalar_mul_owned(self, scalar: Self::Scalar, compiler: &mut COM) -> Self::Output - where - Self: Sized, - { - self.scalar_mul(&scalar, compiler) - } - - /// Multiplies `self` by `scalar` in `compiler`, modifying `self` in-place. - #[inline] - fn scalar_mul_assign(&mut self, scalar: &Self::Scalar, compiler: &mut COM) - where - Self: ScalarMul + Sized, - { - *self = self.scalar_mul(scalar, compiler); - } -} - -/// Elliptic Curve Pre-processed Scalar Multiplication Operation -pub trait PreprocessedScalarMul: ScalarMul + Sized { - /// Performs the scalar multiplication against a pre-computed table. - /// - /// The pre-computed table is powers of two of `scalar`, such that - /// `table[i] = 2^i * G`. - #[must_use] - fn preprocessed_scalar_mul( - table: &[Self; N], - scalar: &Self::Scalar, - compiler: &mut COM, - ) -> Self::Output; -} - -impl PreprocessedScalarMul for G -where - G: ScalarMul, -{ - #[inline] - fn preprocessed_scalar_mul( - table: &[Self; 1], - scalar: &Self::Scalar, - compiler: &mut COM, - ) -> Self::Output { - table[0].scalar_mul(scalar, compiler) - } -} - -/// Elliptic Curve Group -pub trait Group: PointAdd + PointDouble + ScalarMul {} - -/// Pre-processed Scalar Multiplication Table. -/// -/// This table contains power-of-two multiples of a fixed base group element. -#[cfg_attr( - feature = "serde", - derive(Deserialize, Serialize), - serde( - bound(deserialize = "G: Deserialize<'de>", serialize = "G: Serialize"), - crate = "manta_util::serde", - deny_unknown_fields - ) -)] -#[derive(derivative::Derivative)] -#[derivative(Clone, Debug, Eq, Hash, PartialEq)] -pub struct PreprocessedScalarMulTable { - /// Pre-computed Table - table: BoxArray, -} - -impl PreprocessedScalarMulTable { - /// Builds a new [`PreprocessedScalarMulTable`] collection from `base`, such that `table[i] = 2^i * base`. - #[inline] - pub fn from_base(mut base: G, compiler: &mut COM) -> Self - where - G: Clone + PointAdd + PointDouble, - { - let mut powers = Vec::with_capacity(N); - for _ in 0..N { - powers.push(base.clone()); - base.double_assign(compiler); - } - Self::from_powers_unchecked( - powers - .into_boxed_slice() - .try_into() - .ok() - .expect("The size is correct because we perform `N` insertions."), - ) - } - - /// Builds a new [`PreprocessedScalarMulTable`] collection from a known `table` set without - /// checking if the table is consistent. - #[inline] - pub fn from_powers_unchecked(table: Box<[G; N]>) -> Self { - Self { - table: BoxArray(table), - } - } -} - -impl AsRef<[G; N]> for PreprocessedScalarMulTable { - #[inline] - fn as_ref(&self) -> &[G; N] { - &self.table - } -} - -impl Sample for PreprocessedScalarMulTable -where - G: Clone + PointAdd + PointDouble + Sample, -{ - #[inline] - fn sample(distribution: D, rng: &mut R) -> Self - where - R: CryptoRng + RngCore + ?Sized, - { - Self::from_base(G::sample(distribution, rng), &mut ()) - } -} - -impl ScalarMul for PreprocessedScalarMulTable -where - G: PreprocessedScalarMul, -{ - type Scalar = G::Scalar; - type Output = G::Output; - - #[inline] - fn scalar_mul(&self, scalar: &Self::Scalar, compiler: &mut COM) -> Self::Output { - G::preprocessed_scalar_mul(&self.table, scalar, compiler) - } -} - -/// Elliptic-Curve Diffie Hellman Key Exchange -#[cfg_attr( - feature = "serde", - derive(Deserialize, Serialize), - serde(crate = "manta_util::serde", deny_unknown_fields) -)] -#[derive(derivative::Derivative)] -#[derivative(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)] -pub struct DiffieHellman { - /// Base Generator - generator: G, -} - -impl DiffieHellman { - /// Builds a new [`DiffieHellman`] protocol structure from `generator`. - #[inline] - pub fn new(generator: G) -> Self { - Self { generator } - } - - /// Returns a shared reference to the generator for this protocol. - #[inline] - pub fn generator(&self) -> &G { - &self.generator - } - - /// Converts `self` into its underlying generator. - #[inline] - pub fn into_generator(self) -> G { - self.generator - } -} - -impl Constant for DiffieHellman -where - G: Constant, -{ - type Type = DiffieHellman; - - #[inline] - fn new_constant(value: &Self::Type, compiler: &mut COM) -> Self { - Self::new(G::new_constant(&value.generator, compiler)) - } -} - -impl Decode for DiffieHellman -where - G: Decode, -{ - type Error = G::Error; - - #[inline] - fn decode(reader: R) -> Result> - where - R: Read, - { - Ok(Self::new(G::decode(reader)?)) - } -} - -impl Encode for DiffieHellman -where - G: Encode, -{ - #[inline] - fn encode(&self, writer: W) -> Result<(), W::Error> - where - W: Write, - { - self.generator.encode(writer) - } -} - -impl KeyDerivationFunction for DiffieHellman -where - G: ScalarMul, -{ - type Key = G::Scalar; - type Output = G::Output; - - #[inline] - fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { - self.generator.scalar_mul(key, compiler) - } -} - -impl KeyAgreementScheme for DiffieHellman -where - G: ScalarMul, - G::Output: ScalarMul, -{ - type SecretKey = G::Scalar; - type PublicKey = G::Output; - type SharedSecret = G::Output; - - #[inline] - fn agree( - &self, - secret_key: &Self::SecretKey, - public_key: &Self::PublicKey, - compiler: &mut COM, - ) -> Self::SharedSecret { - public_key.scalar_mul(secret_key, compiler) - } -} - -impl Sample for DiffieHellman -where - G: Sample, -{ - #[inline] - fn sample(distribution: D, rng: &mut R) -> Self - where - R: CryptoRng + RngCore + ?Sized, - { - Self::new(G::sample(distribution, rng)) - } -} diff --git a/manta-crypto/src/encryption/hybrid.rs b/manta-crypto/src/encryption/hybrid.rs index fcea0bd3e..1ae132980 100644 --- a/manta-crypto/src/encryption/hybrid.rs +++ b/manta-crypto/src/encryption/hybrid.rs @@ -18,7 +18,11 @@ use crate::{ encryption::symmetric::SymmetricKeyEncryptionScheme, - key::{KeyAgreementScheme, KeyDerivationFunction}, + key::{ + self, + agreement::{Agree, Derive}, + kdf::KeyDerivationFunction, + }, rand::{CryptoRng, Rand, RngCore, Sample}, }; use core::{fmt::Debug, hash::Hash}; @@ -30,7 +34,7 @@ use manta_util::serde::{Deserialize, Serialize}; /// Hybrid Public Key Encryption Scheme pub trait HybridPublicKeyEncryptionScheme: SymmetricKeyEncryptionScheme { /// Key Agreement Scheme Type - type KeyAgreementScheme: KeyAgreementScheme; + type KeyAgreementScheme: key::agreement::Agree + key::agreement::Derive; /// Key Derivation Function Type type KeyDerivationFunction: KeyDerivationFunction< @@ -51,18 +55,18 @@ pub trait HybridPublicKeyEncryptionScheme: SymmetricKeyEncryptionScheme { /// /// # Implementation Note /// - /// This method is an optimization path for calling [`KeyAgreementScheme::agree`] and then + /// This method is an optimization path for calling [`Agree::agree`] and then /// [`KeyDerivationFunction::derive`]. #[inline] fn agree_derive( &self, - secret_key: &SecretKey, public_key: &PublicKey, + secret_key: &SecretKey, ) -> SymmetricKey { self.key_derivation_function().derive( &self .key_agreement_scheme() - .agree(secret_key, public_key, &mut ()), + .agree(public_key, secret_key, &mut ()), &mut (), ) } @@ -70,14 +74,14 @@ pub trait HybridPublicKeyEncryptionScheme: SymmetricKeyEncryptionScheme { /// Secret Key Type pub type SecretKey = - <::KeyAgreementScheme as KeyAgreementScheme>::SecretKey; + <::KeyAgreementScheme as key::agreement::Types>::SecretKey; /// Public Key Type pub type PublicKey = - <::KeyAgreementScheme as KeyAgreementScheme>::PublicKey; + <::KeyAgreementScheme as key::agreement::Types>::PublicKey; /// Shared Secret Type -pub type SharedSecret = <::KeyAgreementScheme as KeyAgreementScheme>::SharedSecret; +pub type SharedSecret = <::KeyAgreementScheme as key::agreement::Types>::SharedSecret; /// Symmetric Key Type pub type SymmetricKey = ::Key; @@ -101,7 +105,7 @@ pub type SymmetricKey = ::Key; #[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Hybrid where - K: KeyAgreementScheme, + K: key::agreement::Agree + key::agreement::Derive, F: KeyDerivationFunction, S: SymmetricKeyEncryptionScheme, { @@ -117,7 +121,7 @@ where impl Hybrid where - K: KeyAgreementScheme, + K: key::agreement::Agree + key::agreement::Derive, F: KeyDerivationFunction, S: SymmetricKeyEncryptionScheme, { @@ -139,7 +143,7 @@ where impl HybridPublicKeyEncryptionScheme for Hybrid where - K: KeyAgreementScheme, + K: key::agreement::Agree + key::agreement::Derive, F: KeyDerivationFunction, S: SymmetricKeyEncryptionScheme, { @@ -159,7 +163,7 @@ where impl Decode for Hybrid where - K: Decode + KeyAgreementScheme, + K: Decode + key::agreement::Agree + key::agreement::Derive, F: Decode + KeyDerivationFunction, S: Decode + SymmetricKeyEncryptionScheme, { @@ -182,7 +186,7 @@ where impl Encode for Hybrid where - K: Encode + KeyAgreementScheme, + K: Encode + key::agreement::Agree + key::agreement::Derive, F: Encode + KeyDerivationFunction, S: Encode + SymmetricKeyEncryptionScheme, { @@ -200,7 +204,7 @@ where impl Sample<(KD, FD, SD)> for Hybrid where - K: KeyAgreementScheme + Sample, + K: key::agreement::Agree + key::agreement::Derive + Sample, F: KeyDerivationFunction + Sample, S: SymmetricKeyEncryptionScheme + Sample, { @@ -219,7 +223,7 @@ where impl SymmetricKeyEncryptionScheme for Hybrid where - K: KeyAgreementScheme, + K: key::agreement::Agree + key::agreement::Derive, F: KeyDerivationFunction, S: SymmetricKeyEncryptionScheme, { @@ -287,7 +291,7 @@ where ) -> Self { Self { ciphertext: cipher.encrypt( - cipher.agree_derive(ephemeral_secret_key, public_key), + cipher.agree_derive(public_key, ephemeral_secret_key), plaintext, ), ephemeral_public_key: cipher @@ -311,7 +315,7 @@ where secret_key: &SecretKey, ) -> Result, Self> { match cipher.decrypt( - cipher.agree_derive(secret_key, &self.ephemeral_public_key), + cipher.agree_derive(&self.ephemeral_public_key, secret_key), &self.ciphertext, ) { Some(plaintext) => Ok(DecryptedMessage::new(self.ephemeral_public_key, plaintext)), diff --git a/manta-crypto/src/key.rs b/manta-crypto/src/key.rs index ce605a37a..635104d76 100644 --- a/manta-crypto/src/key.rs +++ b/manta-crypto/src/key.rs @@ -16,101 +16,139 @@ //! Cryptographic Key Primitives -/// Key Derivation Function -pub trait KeyDerivationFunction { - /// Input Key Type - type Key: ?Sized; - - /// Output Key Type - type Output; - - /// Derives a key of type [`Output`](Self::Output) from `key`. - fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output; - - /// Derives a key of type [`Output`](Self::Output) from `key`. - /// - /// # Implementation Note - /// - /// This method is an optimization path for [`derive`] when the `key` value is owned, and by - /// default, [`derive`] is used as its implementation. This method must return the same value - /// as [`derive`] on the same input. - /// - /// [`derive`]: Self::derive - #[inline] - fn derive_owned(&self, key: Self::Key, compiler: &mut COM) -> Self::Output +/// Key Agreement Schemes +pub mod agreement { + /// Types + pub trait Types { + /// Secret Key Type + type SecretKey; + + /// Public Key Type + type PublicKey; + + /// Shared Secret Type + type SharedSecret; + } + + impl Types for &K where - Self::Key: Sized, + K: Types, { - self.derive(&key, compiler) + type SecretKey = K::SecretKey; + type PublicKey = K::PublicKey; + type SharedSecret = K::SharedSecret; } - /// Borrows `self` rather than consuming it, returning an implementation of - /// [`KeyDerivationFunction`]. - #[inline] - fn by_ref(&self) -> &Self { - self + /// Secret Key Type + pub type SecretKey = ::SecretKey; + + /// Public Key Type + pub type PublicKey = ::PublicKey; + + /// Shared Secret Type + pub type SharedSecret = ::SharedSecret; + + /// Public Key Derivation + pub trait Derive: Types { + /// Derives a [`PublicKey`](Types::PublicKey) from `secret_key`. + fn derive(&self, secret_key: &Self::SecretKey, compiler: &mut COM) -> Self::PublicKey; } -} -impl KeyDerivationFunction for &F -where - F: KeyDerivationFunction, -{ - type Key = F::Key; - type Output = F::Output; + impl Derive for &K + where + K: Derive, + { + #[inline] + fn derive(&self, secret_key: &Self::SecretKey, compiler: &mut COM) -> Self::PublicKey { + (*self).derive(secret_key, compiler) + } + } - #[inline] - fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { - (*self).derive(key, compiler) + /// Key Agreement + pub trait Agree: Types { + /// Performs the agreement protocol on `public_key` and `secret_key` to arrive at the + /// [`SharedSecret`](Types::SharedSecret). + fn agree( + &self, + public_key: &Self::PublicKey, + secret_key: &Self::SecretKey, + compiler: &mut COM, + ) -> Self::SharedSecret; } - #[inline] - fn derive_owned(&self, key: Self::Key, compiler: &mut COM) -> Self::Output + impl Agree for &K where - Self::Key: Sized, + K: Agree, { - (*self).derive_owned(key, compiler) + #[inline] + fn agree( + &self, + public_key: &Self::PublicKey, + secret_key: &Self::SecretKey, + compiler: &mut COM, + ) -> Self::SharedSecret { + (*self).agree(public_key, secret_key, compiler) + } + } + + /// Testing Framework + #[cfg(feature = "test")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "test")))] + pub mod test { + use super::*; + use core::fmt::Debug; + + /// Tests if the `agreement` property is satisfied for `K`. + #[inline] + pub fn agreement(scheme: &K, lhs: &K::SecretKey, rhs: &K::SecretKey) + where + K: Agree + Derive, + K::SharedSecret: Debug + PartialEq, + { + assert_eq!( + scheme.agree(&scheme.derive(rhs, &mut ()), lhs, &mut ()), + scheme.agree(&scheme.derive(lhs, &mut ()), rhs, &mut ()), + "Key agreement schemes should satisfy the agreement property." + ) + } } } -/// Key Derivation Function Adapters +/// Key Derivation Functions pub mod kdf { - use super::*; use crate::rand::{CryptoRng, RngCore, Sample}; - use alloc::vec::Vec; use core::marker::PhantomData; use manta_util::codec::{Decode, DecodeError, Encode, Read, Write}; #[cfg(feature = "serde")] use manta_util::serde::{Deserialize, Serialize}; - /// Identity Key Derivation Function - #[cfg_attr( - feature = "serde", - derive(Deserialize, Serialize), - serde(crate = "manta_util::serde") - )] - #[derive(derivative::Derivative)] - #[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct Identity(PhantomData<(K, COM)>) - where - K: Clone; + /// Key Derivation Function + pub trait KeyDerivationFunction { + /// Key Type + type Key: ?Sized; - impl KeyDerivationFunction for Identity + /// Output Type + type Output; + + /// Derives a key of type [`Output`](Self::Output) from `key`. + fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output; + } + + impl KeyDerivationFunction for &K where - K: Clone, + K: KeyDerivationFunction, { - type Key = K; - type Output = K; + type Key = K::Key; + type Output = K::Output; #[inline] fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { - let _ = compiler; - key.clone() + (*self).derive(key, compiler) } } - /// From Byte Slice Reference Adapter + /// Identity Key Derivation Function #[cfg_attr( feature = "serde", derive(Deserialize, Serialize), @@ -118,93 +156,21 @@ pub mod kdf { )] #[derive(derivative::Derivative)] #[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct FromByteSliceRef - where - T: AsRef<[u8]>, - F: KeyDerivationFunction, - { - /// Key Derivation Function - key_derivation_function: F, - - /// Type Parameter Marker - __: PhantomData<(T, COM)>, - } - - impl FromByteSliceRef - where - T: AsRef<[u8]>, - F: KeyDerivationFunction, - { - /// Builds a new [`FromByteSliceRef`] adapter for `key_derivation_function`. - #[inline] - pub fn new(key_derivation_function: F) -> Self { - Self { - key_derivation_function, - __: PhantomData, - } - } - } - - impl Decode for FromByteSliceRef - where - T: AsRef<[u8]>, - F: Decode + KeyDerivationFunction, - { - // NOTE: We use a blank error here for simplicity. This trait will be removed in the future - // anyways. See https://github.com/Manta-Network/manta-rs/issues/27. - type Error = (); - - #[inline] - fn decode(mut reader: R) -> Result> - where - R: Read, - { - Ok(Self::new( - F::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, - )) - } - } - - impl Encode for FromByteSliceRef + pub struct Identity(PhantomData<(K, COM)>) where - T: AsRef<[u8]>, - F: Encode + KeyDerivationFunction, - { - #[inline] - fn encode(&self, mut writer: W) -> Result<(), W::Error> - where - W: Write, - { - self.key_derivation_function.encode(&mut writer)?; - Ok(()) - } - } + K: Clone; - impl KeyDerivationFunction for FromByteSliceRef + impl KeyDerivationFunction for Identity where - T: AsRef<[u8]>, - F: KeyDerivationFunction, + K: Clone, { - type Key = T; - type Output = F::Output; + type Key = K; + type Output = K; #[inline] fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { - self.key_derivation_function.derive(key.as_ref(), compiler) - } - } - - impl Sample for FromByteSliceRef - where - T: AsRef<[u8]>, - F: KeyDerivationFunction + Sample, - { - #[inline] - fn sample(distribution: D, rng: &mut R) -> Self - where - R: CryptoRng + RngCore + ?Sized, - { - Self::new(F::sample(distribution, rng)) + let _ = compiler; + key.clone() } } @@ -313,116 +279,3 @@ pub mod kdf { } } } - -/// Key Agreement Scheme -/// -/// # Specification -/// -/// All implementations of this trait must adhere to the following properties: -/// -/// 1. **Agreement**: For all possible inputs, the following function returns `true`: -/// -/// ```text -/// fn agreement(lhs: SecretKey, rhs: SecretKey) -> bool { -/// agree(lhs, derive(rhs)) == agree(rhs, derive(lhs)) -/// } -/// ``` -/// This ensures that both parties in the shared computation will arrive at the same conclusion -/// about the value of the [`SharedSecret`](Self::SharedSecret). -pub trait KeyAgreementScheme: - KeyDerivationFunction -{ - /// Secret Key Type - type SecretKey; - - /// Public Key Type - type PublicKey; - - /// Shared Secret Type - type SharedSecret; - - /// Computes the shared secret given the known `secret_key` and the given `public_key`. - fn agree( - &self, - secret_key: &Self::SecretKey, - public_key: &Self::PublicKey, - compiler: &mut COM, - ) -> Self::SharedSecret; - - /// Computes the shared secret given the known `secret_key` and the given `public_key`. - /// - /// # Implementation Note - /// - /// This method is an optimization path for [`agree`] when the `secret_key` value and - /// `public_key` value are owned, and by default, [`agree`] is used as its implementation. This - /// method must return the same value as [`agree`] on the same input. - /// - /// [`agree`]: Self::agree - #[inline] - fn agree_owned( - &self, - secret_key: Self::SecretKey, - public_key: Self::PublicKey, - compiler: &mut COM, - ) -> Self::SharedSecret { - self.agree(&secret_key, &public_key, compiler) - } - - /// Borrows `self` rather than consuming it, returning an implementation of - /// [`KeyAgreementScheme`]. - #[inline] - fn by_ref(&self) -> &Self { - self - } -} - -impl KeyAgreementScheme for &K -where - K: KeyAgreementScheme, -{ - type SecretKey = K::SecretKey; - type PublicKey = K::PublicKey; - type SharedSecret = K::SharedSecret; - - #[inline] - fn agree( - &self, - secret_key: &Self::SecretKey, - public_key: &Self::PublicKey, - compiler: &mut COM, - ) -> Self::SharedSecret { - (*self).agree(secret_key, public_key, compiler) - } - - #[inline] - fn agree_owned( - &self, - secret_key: Self::SecretKey, - public_key: Self::PublicKey, - compiler: &mut COM, - ) -> Self::SharedSecret { - (*self).agree_owned(secret_key, public_key, compiler) - } -} - -/// Testing Framework -#[cfg(feature = "test")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "test")))] -pub mod test { - use super::*; - use core::fmt::Debug; - - /// Tests if the `agreement` property is satisfied for `K`. - #[inline] - pub fn key_agreement(scheme: &K, lhs: &K::SecretKey, rhs: &K::SecretKey) - where - K: KeyAgreementScheme, - K::SharedSecret: Debug + PartialEq, - { - assert_eq!( - scheme.agree(lhs, &scheme.derive(rhs, &mut ()), &mut ()), - scheme.agree(rhs, &scheme.derive(lhs, &mut ()), &mut ()), - "Key agreement schemes should satisfy the agreement property." - ) - } -} diff --git a/manta-crypto/src/lib.rs b/manta-crypto/src/lib.rs index cfc84fa3d..25d5de532 100644 --- a/manta-crypto/src/lib.rs +++ b/manta-crypto/src/lib.rs @@ -24,9 +24,9 @@ extern crate alloc; pub mod accumulator; +pub mod algebra; pub mod commitment; pub mod constraint; -pub mod ecc; pub mod eclair; pub mod encryption; pub mod hash; diff --git a/manta-pay/src/bin/measure.rs b/manta-pay/src/bin/measure.rs index 29189eb56..8c56965d1 100644 --- a/manta-pay/src/bin/measure.rs +++ b/manta-pay/src/bin/measure.rs @@ -19,7 +19,7 @@ use manta_crypto::{ constraint::{measure::Instrument, Allocate, Allocator, Secret}, hash::ArrayHashFunction, - key::{KeyAgreementScheme as _, KeyDerivationFunction}, + key::agreement::{Agree, Derive}, rand::{Sample, SeedableRng}, }; use manta_pay::config::{ @@ -67,7 +67,7 @@ pub fn main() { }); let _ = instrument.measure("DHKE `agree`", |compiler| { - key_agreement.agree(&secret_key_1, &public_key_0, compiler) + key_agreement.agree(&public_key_0, &secret_key_1, compiler) }); println!("{:#?}", instrument.measurements); diff --git a/manta-pay/src/config.rs b/manta-pay/src/config.rs index 1641e8587..14b5df878 100644 --- a/manta-pay/src/config.rs +++ b/manta-pay/src/config.rs @@ -38,10 +38,10 @@ use manta_accounting::{ }; use manta_crypto::{ accumulator, + algebra::DiffieHellman, constraint::{ self, Add, Allocate, Allocator, Constant, ProofSystemInput, Public, Secret, Variable, }, - ecc::DiffieHellman, encryption, hash::ArrayHashFunction, key, merkle_tree, @@ -133,13 +133,13 @@ impl poseidon::arkworks::Specification for PoseidonSpec<4> { pub type KeyAgreementScheme = DiffieHellman; /// Secret Key Type -pub type SecretKey = ::SecretKey; +pub type SecretKey = ::SecretKey; /// Public Key Type -pub type PublicKey = ::PublicKey; +pub type PublicKey = ::PublicKey; /// Key Agreement Scheme Variable Type -pub type KeyAgreementSchemeVar = DiffieHellman; +pub type KeyAgreementSchemeVar = DiffieHellman; /// Unspent Transaction Output Type pub type Utxo = Fp; @@ -258,7 +258,7 @@ pub type VoidNumber = Fp; pub struct VoidNumberCommitmentScheme(pub Poseidon2); impl transfer::VoidNumberCommitmentScheme for VoidNumberCommitmentScheme { - type SecretSpendKey = ::SecretKey; + type SecretSpendKey = SecretKey; type Utxo = Utxo; type VoidNumber = VoidNumber; @@ -321,7 +321,7 @@ pub type VoidNumberVar = ConstraintFieldVar; pub struct VoidNumberCommitmentSchemeVar(pub Poseidon2Var); impl transfer::VoidNumberCommitmentScheme for VoidNumberCommitmentSchemeVar { - type SecretSpendKey = >::SecretKey; + type SecretSpendKey = ::SecretKey; type Utxo = >::Utxo; type VoidNumber = ConstraintFieldVar; @@ -672,7 +672,7 @@ pub type NoteSymmetricEncryptionScheme = encryption::symmetric::Map< pub type NoteEncryptionScheme = encryption::hybrid::Hybrid< KeyAgreementScheme, key::kdf::FromByteVector< - ::SharedSecret, + ::SharedSecret, Blake2sKdf, >, NoteSymmetricEncryptionScheme, @@ -686,13 +686,11 @@ pub type Ciphertext = pub struct Config; impl transfer::Configuration for Config { - type SecretKey = ::SecretKey; - type PublicKey = ::PublicKey; + type SecretKey = SecretKey; + type PublicKey = PublicKey; type KeyAgreementScheme = KeyAgreementScheme; - type SecretKeyVar = - >::SecretKey; - type PublicKeyVar = - >::PublicKey; + type SecretKeyVar = ::SecretKey; + type PublicKeyVar = ::PublicKey; type KeyAgreementSchemeVar = KeyAgreementSchemeVar; type Utxo = ::Utxo; type UtxoCommitmentScheme = UtxoCommitmentScheme; diff --git a/manta-pay/src/crypto/constraint/arkworks/mod.rs b/manta-pay/src/crypto/constraint/arkworks/mod.rs index b51982ca9..81ba2c5eb 100644 --- a/manta-pay/src/crypto/constraint/arkworks/mod.rs +++ b/manta-pay/src/crypto/constraint/arkworks/mod.rs @@ -24,6 +24,7 @@ use ark_relations::{ r1cs::{ConstraintSynthesizer, ConstraintSystemRef}, }; use manta_crypto::{ + algebra, constraint::{ self, measure::{Count, Measure}, @@ -188,6 +189,21 @@ where } } +impl algebra::Scalar for Fp +where + F: Field, +{ + #[inline] + fn add(&self, rhs: &Self, _: &mut ()) -> Self { + Self(self.0.add(rhs.0)) + } + + #[inline] + fn mul(&self, rhs: &Self, _: &mut ()) -> Self { + Self(self.0.mul(rhs.0)) + } +} + impl SizeLimit for Fp where F: PrimeField, diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index c638cce1a..f3dae0e6b 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -24,8 +24,8 @@ use ark_relations::ns; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, SerializationError}; use core::marker::PhantomData; use manta_crypto::{ + algebra, constraint::{self, Allocate, Allocator, Constant, Public, Secret, Variable}, - ecc::{self, PointAdd, PointDouble}, key::kdf, rand::{CryptoRng, RngCore, Sample}, }; @@ -43,9 +43,6 @@ type ConstraintField = <::BaseField as Field>::BasePrim /// Compiler Type type Compiler = R1CS>; -/// Curve Scalar Parameter -type ScalarParam = <::ScalarField as PrimeField>::Params; - /// Scalar Field Element pub type Scalar = Fp<::ScalarField>; @@ -232,19 +229,33 @@ where } } -impl ecc::ScalarMul for Group +impl algebra::Group for Group where C: ProjectiveCurve, { type Scalar = Scalar; - type Output = Self; #[inline] - fn scalar_mul(&self, scalar: &Self::Scalar, _: &mut ()) -> Self::Output { + fn add(&self, rhs: &Self, _: &mut ()) -> Self { + Self([self.0, rhs.0].into_iter().sum()) + } + + #[inline] + fn mul(&self, scalar: &Self::Scalar, _: &mut ()) -> Self { Self(self.0.mul(scalar.0.into_repr()).into()) } } +/// Discrete Logarithm Hardness +/// +/// We assume that the DL problem is hard for all `arkworks` implementations of elliptic curves. +impl algebra::security::DiscreteLogarithmHardness for Group where C: ProjectiveCurve {} + +/// Computational Diffie-Hellman Hardness +/// +/// We assume that the CDH problem is hard for all `arkworks` implementations of elliptic curves. +impl algebra::security::ComputationalDiffieHellmanHardness for Group where C: ProjectiveCurve {} + impl Sample for Group where C: ProjectiveCurve, @@ -317,6 +328,24 @@ where } } +impl algebra::Scalar> for ScalarVar +where + C: ProjectiveCurve, + CV: CurveVar>, +{ + #[inline] + fn add(&self, rhs: &Self, compiler: &mut Compiler) -> Self { + let _ = compiler; + Self::new(&self.0 + &rhs.0) + } + + #[inline] + fn mul(&self, rhs: &Self, compiler: &mut Compiler) -> Self { + let _ = compiler; + Self::new(&self.0 * &rhs.0) + } +} + impl Constant> for ScalarVar where C: ProjectiveCurve, @@ -386,18 +415,25 @@ where } } -impl ecc::ScalarMul> for GroupVar +impl algebra::Group> for GroupVar where C: ProjectiveCurve, CV: CurveVar>, { type Scalar = ScalarVar; - type Output = Self; #[inline] - fn scalar_mul(&self, scalar: &Self::Scalar, compiler: &mut Compiler) -> Self::Output { + fn add(&self, rhs: &Self, compiler: &mut Compiler) -> Self { + let _ = compiler; + let mut result = self.0.clone(); + result += &rhs.0; + Self::new(result) + } + + #[inline] + fn mul(&self, scalar: &Self::Scalar, compiler: &mut Compiler) -> Self { let _ = compiler; - Self( + Self::new( self.0 .scalar_mul_le( scalar @@ -407,49 +443,29 @@ where .iter(), ) .expect("Scalar multiplication is not allowed to fail."), - PhantomData, ) } } -macro_rules! impl_processed_scalar_mul { - ($curve: ty) => { - impl - ecc::PreprocessedScalarMul< - Compiler<$curve>, - { - <<$curve as ProjectiveCurve>::ScalarField as PrimeField>::Params::MODULUS_BITS - as usize - }, - > for GroupVar<$curve, CV> - where - CV: CurveVar<$curve, ConstraintField<$curve>>, - { - #[inline] - fn preprocessed_scalar_mul( - table: &[Self; ScalarParam::<$curve>::MODULUS_BITS as usize], - scalar: &Self::Scalar, - compiler: &mut Compiler<$curve>, - ) -> Self::Output { - let _ = compiler; - let mut result = CV::zero(); - let scalar_bits = scalar - .0 - .to_bits_le() - .expect("Bit decomposition is not allowed to fail."); - // TODO: Add `+` implementations, `conditional_add` to avoid unnecessary clones. - for (bit, base) in scalar_bits.into_iter().zip(table.iter()) { - result = bit - .select(&(result.clone() + &base.0), &result) - .expect("Conditional select is not allowed to fail. "); - } - Self(result, PhantomData) - } - } - }; +/// Discrete Logarithm Hardness +/// +/// We assume that the DL problem is hard for all `arkworks` implementations of elliptic curves. +impl algebra::security::DiscreteLogarithmHardness for GroupVar +where + C: ProjectiveCurve, + CV: CurveVar>, +{ } -impl_processed_scalar_mul!(ark_ed_on_bls12_381::EdwardsProjective); +/// Computational Diffie-Hellman Hardness +/// +/// We assume that the CDH problem is hard for all `arkworks` implementations of elliptic curves. +impl algebra::security::ComputationalDiffieHellmanHardness for GroupVar +where + C: ProjectiveCurve, + CV: CurveVar>, +{ +} impl constraint::PartialEq> for GroupVar where @@ -540,82 +556,3 @@ where ) } } - -impl PointAdd> for GroupVar -where - C: ProjectiveCurve, - CV: CurveVar>, -{ - type Output = Self; - - #[inline] - fn add(&self, rhs: &Self, compiler: &mut Compiler) -> Self::Output { - let _ = compiler; - let mut result = self.0.clone(); - result += &rhs.0; - Self::new(result) - } -} - -impl PointDouble> for GroupVar -where - C: ProjectiveCurve, - CV: CurveVar>, -{ - type Output = Self; - - #[inline] - fn double(&self, compiler: &mut Compiler) -> Self::Output { - let _ = compiler; - Self::new(self.0.double().expect("Doubling is not allowed to fail.")) - } -} - -#[cfg(test)] -mod test { - use super::*; - use ark_ec::ProjectiveCurve; - use ark_ed_on_bls12_381::{constraints::EdwardsVar, EdwardsProjective}; - use ecc::PreprocessedScalarMul; - use manta_crypto::{ - constraint::AssertEq, - ecc::{PreprocessedScalarMulTable, ScalarMul}, - rand::OsRng, - }; - - /// Tests preprocessed scalar multiplication on curve `C`. - #[inline] - fn preprocessed_scalar_mul_test_template(rng: &mut OsRng) - where - C: ProjectiveCurve, - CV: CurveVar>, - GroupVar: PreprocessedScalarMul< - Compiler, - N, - Scalar = ScalarVar, - Output = GroupVar, - >, - { - const NUM_TRIALS: usize = 5; - let mut cs = R1CS::for_proofs(); - for _ in 0..NUM_TRIALS { - let base = Group::gen(rng).as_known::>(&mut cs); - let scalar = Scalar::::gen(rng).as_known::(&mut cs); - let expected = base.scalar_mul(&scalar, &mut cs); - let table = PreprocessedScalarMulTable::<_, N>::from_base(base, &mut cs); - let actual = table.scalar_mul(&scalar, &mut cs); - cs.assert_eq(&expected, &actual); - } - assert!(cs.is_satisfied()); - } - - /// Tests preprocessed scalar multiplication on different curves. - #[test] - fn preprocessed_scalar_mul() { - preprocessed_scalar_mul_test_template::< - EdwardsProjective, - EdwardsVar, - { ScalarParam::::MODULUS_BITS as usize }, - >(&mut OsRng); - } -} diff --git a/manta-pay/src/crypto/key.rs b/manta-pay/src/crypto/key.rs index d79ae1435..15038e3be 100644 --- a/manta-pay/src/crypto/key.rs +++ b/manta-pay/src/crypto/key.rs @@ -18,7 +18,7 @@ use blake2::{Blake2s, Digest}; use manta_crypto::{ - key::KeyDerivationFunction, + key::kdf::KeyDerivationFunction, rand::{CryptoRng, RngCore, Sample}, }; use manta_util::{impl_empty_codec, into_array_unchecked}; diff --git a/manta-pay/src/signer/base.rs b/manta-pay/src/signer/base.rs index 89cb13d4d..9cdb46453 100644 --- a/manta-pay/src/signer/base.rs +++ b/manta-pay/src/signer/base.rs @@ -34,7 +34,9 @@ use manta_accounting::{ signer::{self, AssetMapKey, SyncData}, }, }; -use manta_crypto::{key::KeyDerivationFunction, merkle_tree, merkle_tree::forest::Configuration}; +use manta_crypto::{ + key::kdf::KeyDerivationFunction, merkle_tree, merkle_tree::forest::Configuration, +}; #[cfg(feature = "serde")] use manta_util::serde::{Deserialize, Serialize}; From a188064b009242553f8a22867e82e2d71d6a01f4 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 24 Jun 2022 17:29:51 -0400 Subject: [PATCH 2/7] chore: add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f31fcf555..df7215362 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - [\#130](https://github.com/Manta-Network/manta-rs/pull/130) Add the sage script and the hardcoded tests for the security of mds matrix ### Changed +- [\#132](https://github.com/Manta-Network/manta-rs/pull/132) Simplify algebra APIs and removing ECC-specific design ### Deprecated From 909fcd5eebef4f8ba6216af2dfc77decb3fea9ef Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 24 Jun 2022 17:34:15 -0400 Subject: [PATCH 3/7] fix: import `alloc::vec::Vec` for `AsBytes` --- manta-crypto/src/key.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/manta-crypto/src/key.rs b/manta-crypto/src/key.rs index 635104d76..127a5d2a6 100644 --- a/manta-crypto/src/key.rs +++ b/manta-crypto/src/key.rs @@ -117,6 +117,7 @@ pub mod agreement { /// Key Derivation Functions pub mod kdf { use crate::rand::{CryptoRng, RngCore, Sample}; + use alloc::vec::Vec; use core::marker::PhantomData; use manta_util::codec::{Decode, DecodeError, Encode, Read, Write}; From 4c5f1d1c1458ce1c52210fccfbf5721731db94bd Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Fri, 24 Jun 2022 17:48:30 -0400 Subject: [PATCH 4/7] chore: remove stray merge conflict --- manta-crypto/src/key.rs | 101 ---------------------------------------- 1 file changed, 101 deletions(-) diff --git a/manta-crypto/src/key.rs b/manta-crypto/src/key.rs index 2280ada4b..97369f274 100644 --- a/manta-crypto/src/key.rs +++ b/manta-crypto/src/key.rs @@ -175,107 +175,6 @@ pub mod kdf { } } -<<<<<<< HEAD -======= - /// From Byte Slice Reference Adapter - #[cfg_attr( - feature = "serde", - derive(Deserialize, Serialize), - serde(crate = "manta_util::serde") - )] - #[derive(derivative::Derivative)] - #[derivative(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] - pub struct FromByteSliceRef - where - T: AsRef<[u8]>, - F: KeyDerivationFunction, - { - /// Key Derivation Function - key_derivation_function: F, - - /// Type Parameter Marker - __: PhantomData<(T, COM)>, - } - - impl FromByteSliceRef - where - T: AsRef<[u8]>, - F: KeyDerivationFunction, - { - /// Builds a new [`FromByteSliceRef`] adapter for `key_derivation_function`. - #[inline] - pub fn new(key_derivation_function: F) -> Self { - Self { - key_derivation_function, - __: PhantomData, - } - } - } - - impl Decode for FromByteSliceRef - where - T: AsRef<[u8]>, - F: Decode + KeyDerivationFunction, - { - // NOTE: We use a blank error here for simplicity. This trait will be removed in the future - // anyways. See https://github.com/Manta-Network/manta-rs/issues/27. - type Error = (); - - #[inline] - fn decode(mut reader: R) -> Result> - where - R: Read, - { - Ok(Self::new( - F::decode(&mut reader).map_err(|err| err.map_decode(|_| ()))?, - )) - } - } - - impl Encode for FromByteSliceRef - where - T: AsRef<[u8]>, - F: Encode + KeyDerivationFunction, - { - #[inline] - fn encode(&self, mut writer: W) -> Result<(), W::Error> - where - W: Write, - { - self.key_derivation_function.encode(&mut writer)?; - Ok(()) - } - } - - impl KeyDerivationFunction for FromByteSliceRef - where - T: AsRef<[u8]>, - F: KeyDerivationFunction, - { - type Key = T; - type Output = F::Output; - - #[inline] - fn derive(&self, key: &Self::Key, compiler: &mut COM) -> Self::Output { - self.key_derivation_function.derive(key.as_ref(), compiler) - } - } - - impl Sample for FromByteSliceRef - where - T: AsRef<[u8]>, - F: KeyDerivationFunction + Sample, - { - #[inline] - fn sample(distribution: D, rng: &mut R) -> Self - where - R: RngCore + ?Sized, - { - Self::new(F::sample(distribution, rng)) - } - } - ->>>>>>> main /// Byte Conversion Trait pub trait AsBytes { /// Returns an owned byte representation of `self`. From 368640eaad31ae8b8fb3491012a139d25acf6cc0 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Sun, 26 Jun 2022 12:21:57 -0400 Subject: [PATCH 5/7] fix: remove extra `CryptoRng` requirement Co-authored-by: Tom Shen Signed-off-by: Brandon H. Gomes --- manta-crypto/src/algebra.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manta-crypto/src/algebra.rs b/manta-crypto/src/algebra.rs index a60c38431..ab7b93f43 100644 --- a/manta-crypto/src/algebra.rs +++ b/manta-crypto/src/algebra.rs @@ -163,7 +163,7 @@ where #[inline] fn sample(distribution: D, rng: &mut R) -> Self where - R: CryptoRng + RngCore + ?Sized, + R: RngCore + ?Sized, { Self::new(G::sample(distribution, rng)) } From fece287a56b893c6be0a95075d307afab659707e Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Sun, 26 Jun 2022 12:26:06 -0400 Subject: [PATCH 6/7] fix: remove unused `CryptoRng` import --- manta-crypto/src/algebra.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manta-crypto/src/algebra.rs b/manta-crypto/src/algebra.rs index a60c38431..5f01b39ec 100644 --- a/manta-crypto/src/algebra.rs +++ b/manta-crypto/src/algebra.rs @@ -19,7 +19,7 @@ use crate::{ eclair::alloc::Constant, key, - rand::{CryptoRng, RngCore, Sample}, + rand::{RngCore, Sample}, }; use core::marker::PhantomData; use manta_util::codec::{Decode, DecodeError, Encode, Read, Write}; From 76fcd41711e48f2073fe9c01c120d514059df9f9 Mon Sep 17 00:00:00 2001 From: "Brandon H. Gomes" Date: Mon, 27 Jun 2022 13:51:25 -0400 Subject: [PATCH 7/7] fix: use canonical `+` and `*` implementations --- manta-pay/src/crypto/constraint/arkworks/mod.rs | 4 ++-- manta-pay/src/crypto/ecc/arkworks.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/manta-pay/src/crypto/constraint/arkworks/mod.rs b/manta-pay/src/crypto/constraint/arkworks/mod.rs index 81ba2c5eb..04d66836e 100644 --- a/manta-pay/src/crypto/constraint/arkworks/mod.rs +++ b/manta-pay/src/crypto/constraint/arkworks/mod.rs @@ -195,12 +195,12 @@ where { #[inline] fn add(&self, rhs: &Self, _: &mut ()) -> Self { - Self(self.0.add(rhs.0)) + Self(self.0 + rhs.0) } #[inline] fn mul(&self, rhs: &Self, _: &mut ()) -> Self { - Self(self.0.mul(rhs.0)) + Self(self.0 * rhs.0) } } diff --git a/manta-pay/src/crypto/ecc/arkworks.rs b/manta-pay/src/crypto/ecc/arkworks.rs index 956f8ea07..9ca0c333e 100644 --- a/manta-pay/src/crypto/ecc/arkworks.rs +++ b/manta-pay/src/crypto/ecc/arkworks.rs @@ -237,7 +237,7 @@ where #[inline] fn add(&self, rhs: &Self, _: &mut ()) -> Self { - Self([self.0, rhs.0].into_iter().sum()) + Self(self.0 + rhs.0) } #[inline]