Skip to content

Commit

Permalink
major cleanup; doc example now works
Browse files Browse the repository at this point in the history
  • Loading branch information
trbritt committed Aug 16, 2024
1 parent 86c800b commit 457dd08
Show file tree
Hide file tree
Showing 18 changed files with 159 additions and 114 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ subtle = "2.6.1"
crypto-bigint = "0.6.0-rc.2"
sha3 = "0.11.0-pre.4"

[lib]
proc-macro = true

[dev-dependencies]
serde = { version = "1.0.204", features = ["derive"] }
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ fn main() {
let key_pair = KeyPair::generate();
let message = b"Hello, World!";

let signature = sign(&key_pair.secret_key, message);
assert!(verify(&key_pair.public_key, message, &signature));
let signature = sign(&key_pair.secret_key, message).unwrap();
assert!(verify(&key_pair.public_key, message, &signature).unwrap());
}
```

Expand Down
4 changes: 1 addition & 3 deletions src/fields/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
// since the underlying Mul, Add, etc., are not, and const traits are in the works
// https://github.com/rust-lang/rust/issues/67792
#[derive(Copy, Clone, Debug)]
pub(crate) struct FieldExtension<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>>(
pub(crate) [F; N],
);
pub struct FieldExtension<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>>(pub [F; N]);

impl<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> From<u64>
for FieldExtension<D, N, F>
Expand Down
10 changes: 5 additions & 5 deletions src/fields/fp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use num_traits::{Euclid, Inv, One, Pow, Zero};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
use subtle::CtOption;

pub(crate) const BN254_FP_MODULUS: Fp = Fp::new(U256::from_words([
pub const BN254_FP_MODULUS: Fp = Fp::new(U256::from_words([
0x3C208C16D87CFD47,
0x97816A916871CA8D,
0xB85045B68181585D,
Expand All @@ -53,7 +53,7 @@ pub(crate) const BN254_FP_MODULUS: Fp = Fp::new(U256::from_words([
/// a finite field satisfies many rigorous mathematical properties. The
/// (non-exhaustive) list below simply suffices to illustrate those properties
/// that are purely relevant to the task at hand here.
pub(crate) trait FieldExtensionTrait<const D: usize, const N: usize>:
pub trait FieldExtensionTrait<const D: usize, const N: usize>:
Sized
+ Copy
+ Clone
Expand Down Expand Up @@ -119,16 +119,16 @@ macro_rules! define_finite_prime_field {
type $output = crypto_bigint::modular::ConstMontyForm<$mod_struct, { $mod_struct::LIMBS }>;
#[derive(Clone, Debug, Copy)] //to be used in const contexts
pub struct $wrapper_name($mod_struct, $output);

impl FinitePrimeField<$limbs, $uint_type, $degree, $nreps> for $wrapper_name {}

impl $wrapper_name {
// builder structure to create elements in the base field of a given value
pub const fn new(value: $uint_type) -> Self {
Self($mod_struct, $output::new(&value))
}
// this is indeed used in the test cases, which are ignored by
// the linter
// this is indeed used in the test cases, which are ignored by
// the linter
pub fn new_from_str(value: &str) -> Option<Self> {
let ints: Vec<_> = {
let mut acc = Self::zero();
Expand Down
8 changes: 4 additions & 4 deletions src/fields/fp12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ const FP12_QUADRATIC_NON_RESIDUE: Fp12 = Fp12::new(&[
]),
]);

pub(crate) type Fp12 = FieldExtension<12, 2, Fp6>;
pub type Fp12 = FieldExtension<12, 2, Fp6>;

impl FieldExtensionTrait<12, 2> for Fp12 {
fn quadratic_non_residue() -> Self {
Expand Down Expand Up @@ -282,10 +282,10 @@ impl ConditionallySelectable for Fp12 {
}
/// Below are additional functions needed on Fp12 for the pairing operations
impl Fp12 {
pub(crate) fn unitary_inverse(&self) -> Self {
pub fn unitary_inverse(&self) -> Self {
Self::new(&[self.0[0], -self.0[1]])
}
pub(crate) fn pow(&self, arg: &[u64; 4]) -> Self {
pub fn pow(&self, arg: &[u64; 4]) -> Self {
let mut res = Self::one();
for e in arg.iter().rev() {
for i in (0..64).rev() {
Expand Down Expand Up @@ -321,7 +321,7 @@ impl Fp12 {
/// The function below is called by `zcash`, `bn`, and `arkworks` as `mul_by_024`, referring to
/// the indices of the non-zero elements in the 6x Fp2 representation above for the
/// multiplication.
pub(crate) fn sparse_mul(&self, ell_0: Fp2, ell_vw: Fp2, ell_vv: Fp2) -> Fp12 {
pub fn sparse_mul(&self, ell_0: Fp2, ell_vw: Fp2, ell_vv: Fp2) -> Fp12 {
let z0 = self.0[0].0[0];
let z1 = self.0[0].0[1];
let z2 = self.0[0].0[2];
Expand Down
12 changes: 6 additions & 6 deletions src/fields/fp2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
//! the specific behaviour for this extension, such as multiplication.
use crate::fields::extensions::FieldExtension;
use crate::fields::fp::{FieldExtensionTrait, Fp, BN254_FP_MODULUS};
use crypto_bigint::{rand_core::CryptoRngCore, subtle::ConditionallySelectable, U256, U512};
use crypto_bigint::{rand_core::CryptoRngCore, subtle::ConditionallySelectable, U256};
use num_traits::{Inv, One, Pow, Zero};
use std::ops::{Div, DivAssign, Mul, MulAssign};
use subtle::{Choice, ConstantTimeEq, CtOption};

const FP2_QUADRATIC_NON_RESIDUE: Fp2 = Fp2::new(&[Fp::NINE, Fp::ONE]);
pub(crate) const TWO_INV: Fp = Fp::new(U256::from_words([
pub const TWO_INV: Fp = Fp::new(U256::from_words([
11389680472494603940,
14681934109093717318,
15863968012492123182,
Expand Down Expand Up @@ -45,13 +45,13 @@ const FP2_TWIST_CURVE_CONSTANT: Fp2 = Fp2::new(&[
42524369107353300,
])),
]);
pub(crate) type Fp2 = FieldExtension<2, 2, Fp>;
pub type Fp2 = FieldExtension<2, 2, Fp>;

// there are some specific things that must be defined as
// helper functions for us on this specific extension, but
// don't generalize to any extension.
impl Fp2 {
pub(crate) fn pow(&self, by: &Fp) -> Self {
pub fn pow(&self, by: &Fp) -> Self {
let bits = by.value().to_words();
let mut res = Self::one();
for e in bits.iter().rev() {
Expand All @@ -64,8 +64,8 @@ impl Fp2 {
}
res
}
pub(crate) fn residue_mul(&self) -> Self {

pub fn residue_mul(&self) -> Self {
*self * FP2_QUADRATIC_NON_RESIDUE
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/fields/fp6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ const FP6_QUADRATIC_NON_RESIDUE: Fp6 = Fp6::new(&[
Fp2::new(&[Fp::ZERO, Fp::ZERO]),
]);

pub(crate) type Fp6 = FieldExtension<6, 3, Fp2>;
pub type Fp6 = FieldExtension<6, 3, Fp2>;

impl Fp6 {
pub(crate) fn residue_mul(&self) -> Self {
pub fn residue_mul(&self) -> Self {
Self([self.0[2].residue_mul(), self.0[0], self.0[1]])
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/fields/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod extensions;
pub(crate) mod fp;
pub(crate) mod fp12;
pub(crate) mod fp2;
pub(crate) mod fp6;
pub(crate) mod utils;
pub mod fp;
pub mod fp12;
pub mod fp2;
pub mod fp6;
pub mod utils;
30 changes: 15 additions & 15 deletions src/fields/utils.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
use crypto_bigint::{Encoding, U1024, U2048, U256, U4096, U512};
use crypto_bigint::{Encoding, U256, U512};

pub(crate) fn to_larger_uint<const N: usize, const M: usize>(smaller_bytes: &[u8; N]) -> [u8; M] {
pub fn to_larger_uint<const N: usize, const M: usize>(smaller_bytes: &[u8; N]) -> [u8; M] {
assert!(M > N, "Target size must be larger than source size");
let mut larger_bytes = [0u8; M];
larger_bytes[M - N..].copy_from_slice(smaller_bytes);
larger_bytes
}

// Specific conversion functions
pub(crate) fn u256_to_u512(u256: &U256) -> U512 {
pub fn u256_to_u512(u256: &U256) -> U512 {
U512::from_be_bytes(to_larger_uint::<32, 64>(&u256.to_be_bytes()))
}

pub(crate) fn u256_to_u1024(u256: &U256) -> U1024 {
U1024::from_be_bytes(to_larger_uint::<32, 128>(&u256.to_be_bytes()))
}

pub(crate) fn u256_to_u2048(u256: &U256) -> U2048 {
U2048::from_be_bytes(to_larger_uint::<32, 256>(&u256.to_be_bytes()))
}

pub(crate) fn u256_to_u4096(u256: &U256) -> U4096 {
U4096::from_be_bytes(to_larger_uint::<32, 512>(&u256.to_be_bytes()))
}
//
// pub fn u256_to_u1024(u256: &U256) -> U1024 {
// U1024::from_be_bytes(to_larger_uint::<32, 128>(&u256.to_be_bytes()))
// }
//
// pub fn u256_to_u2048(u256: &U256) -> U2048 {
// U2048::from_be_bytes(to_larger_uint::<32, 256>(&u256.to_be_bytes()))
// }
//
// pub fn u256_to_u4096(u256: &U256) -> U4096 {
// U4096::from_be_bytes(to_larger_uint::<32, 512>(&u256.to_be_bytes()))
// }
10 changes: 4 additions & 6 deletions src/groups/g1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ use crypto_bigint::rand_core::CryptoRngCore;
use num_traits::Zero;
use subtle::{Choice, ConstantTimeEq};

pub type G1Affine = GroupAffine<1, 1, Fp>;

pub(crate) type G1Affine = GroupAffine<1, 1, Fp>;

pub(crate) type G1Projective = GroupProjective<1, 1, Fp>;
pub type G1Projective = GroupProjective<1, 1, Fp>;

impl GroupTrait<1, 1, Fp> for G1Affine {
fn generator() -> Self {
Expand Down Expand Up @@ -72,7 +71,7 @@ impl GroupTrait<1, 1, Fp> for G1Affine {
impl G1Affine {
/// this needs to be defined in order to have user interaction, but currently
/// is only visible in tests, and therefore is seen by the linter as unused
pub(crate) fn new(v: [Fp; 2]) -> Result<Self, GroupError> {
pub fn new(v: [Fp; 2]) -> Result<Self, GroupError> {
let _g1affine_is_on_curve = |x: &Fp, y: &Fp, z: &Choice| -> Choice {
let y2 = <Fp as FieldExtensionTrait<1, 1>>::square(y);
let x2 = <Fp as FieldExtensionTrait<1, 1>>::square(x);
Expand Down Expand Up @@ -159,8 +158,7 @@ impl GroupTrait<1, 1, Fp> for G1Projective {
}
}
impl G1Projective {

pub(crate) fn new(v: [Fp; 3]) -> Result<Self, GroupError> {
pub fn new(v: [Fp; 3]) -> Result<Self, GroupError> {
let _g1projective_is_on_curve = |x: &Fp, y: &Fp, z: &Fp| -> Choice {
let y2 = <Fp as FieldExtensionTrait<1, 1>>::square(y);
let x2 = <Fp as FieldExtensionTrait<1, 1>>::square(x);
Expand Down
12 changes: 6 additions & 6 deletions src/groups/g2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const G2_Y: Fp2 = Fp2::new(&[
])),
]);
// the first constant of the endomorphism, $\xi^((p-1)/3)$, see below
pub(crate) const EPS_EXP0: Fp2 = Fp2::new(&[
pub const EPS_EXP0: Fp2 = Fp2::new(&[
Fp::new(U256::from_words([
11088870908804158781,
13226160682434769676,
Expand All @@ -68,7 +68,7 @@ pub(crate) const EPS_EXP0: Fp2 = Fp2::new(&[
])),
]);
// the second constant of the endomorphism, $\xi^((p-1)/2)$, see below
pub(crate) const EPS_EXP1: Fp2 = Fp2::new(&[
pub const EPS_EXP1: Fp2 = Fp2::new(&[
Fp::new(U256::from_words([
15876315988453495642,
15828711151707445656,
Expand All @@ -91,11 +91,11 @@ const C2: Fp = Fp::new(U256::from_words([
0,
]));
// the parameter that generates this member of the BN family
pub(crate) const BLS_X: Fp = Fp::new(U256::from_words([4965661367192848881, 0, 0, 0]));
pub const BLS_X: Fp = Fp::new(U256::from_words([4965661367192848881, 0, 0, 0]));

pub(crate) type G2Affine = GroupAffine<2, 2, Fp2>;
pub type G2Affine = GroupAffine<2, 2, Fp2>;

pub(crate) type G2Projective = GroupProjective<2, 2, Fp2>;
pub type G2Projective = GroupProjective<2, 2, Fp2>;

impl GroupTrait<2, 2, Fp2> for G2Affine {
// This is the generator of $E^\prime(F_{p^2})$, and NOT of the r-torsion. This is because we
Expand Down Expand Up @@ -260,7 +260,7 @@ impl G2Projective {
/// The public entrypoint to making a value in $\mathbb{G}_2$. This takes the (x,y,z) values
/// from the user, and passes them through a subgroup and curve check to ensure validity.
/// Values returned from this function are guaranteed to be on the curve and in the r-torsion.
pub(crate) fn new(v: [Fp2; 3]) -> Result<Self, GroupError> {
pub fn new(v: [Fp2; 3]) -> Result<Self, GroupError> {
let _g2projective_is_on_curve = |x: &Fp2, y: &Fp2, z: &Fp2| -> Choice {
let y2 = <Fp2 as FieldExtensionTrait<2, 2>>::square(y);
let x2 = <Fp2 as FieldExtensionTrait<2, 2>>::square(x);
Expand Down
34 changes: 17 additions & 17 deletions src/groups/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crypto_bigint::subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
use std::ops::{Add, Mul, Neg, Sub};

#[derive(Debug)]
pub(crate) enum GroupError {
pub enum GroupError {
/// This is a simple error struct that specifies the three errors
/// that are expected for the generation of a point on the curve.
/// Either, the coordinates given are not even on the curve,
Expand All @@ -43,7 +43,7 @@ pub(crate) enum GroupError {
// projective, or mixed addition, and therefore cannot be defined for all instances satisfying
// a group trait

pub(crate) trait GroupTrait<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>>:
pub trait GroupTrait<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>>:
Sized + Copy + Clone + std::fmt::Debug + Neg + ConstantTimeEq + ConditionallySelectable + PartialEq
{
/// this is how we'll make more elements of the field from a scalar value
Expand All @@ -58,15 +58,15 @@ pub(crate) trait GroupTrait<const D: usize, const N: usize, F: FieldExtensionTra
}

#[derive(Copy, Clone, Debug)]
pub(crate) struct GroupAffine<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> {
pub struct GroupAffine<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> {
/// this is the implementation of a point on the curve in affine coordinates. It is not possible
/// to directly input a pair of x, y such that infinity is True, since the point at infinity
/// has no unique representation in this form. Generation of the point at infinity is accomplished
/// either by calling the `zero` method, or by applying binary operations to 'normal' points to
/// reach the point at infinity with arithmetic.
pub(crate) x: F,
pub(crate) y: F,
pub(crate) infinity: Choice,
pub x: F,
pub y: F,
pub infinity: Choice,
}
/// this is the beginning of Rust lifetime magic. The issue is that when we implement
/// the arithmetic, we need to explicitly state the lifetime of each operand
Expand Down Expand Up @@ -137,20 +137,20 @@ impl<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> PartialEq
}
}
impl<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> GroupAffine<D, N, F> {
pub(crate) fn zero() -> Self {
pub fn zero() -> Self {
Self {
x: F::zero(),
y: F::one(),
infinity: Choice::from(1u8),
}
}
pub(crate) fn is_zero(&self) -> bool {

pub fn is_zero(&self) -> bool {
bool::from(self.infinity)
}
}
#[derive(Copy, Clone, Debug)]
pub(crate) struct GroupProjective<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> {
pub struct GroupProjective<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> {
/// We now define the projective representation of a point on the curve. Here, the point(s) at
/// infinity is (are) indicated by `z=0`. This allows the user to therefore directly generate
/// such a point with the associated `new` method. Affine coordinates are those indicated by `z=1`.
Expand All @@ -161,24 +161,24 @@ pub(crate) struct GroupProjective<const D: usize, const N: usize, F: FieldExtens
/// projective coords, or (iii) have mixed representations. For security, due to the uniqueness of
/// the representation of the point at infinity, we therefore opt to have
/// all arithmetic done in projective coordinates.
pub(crate) x: F,
pub(crate) y: F,
pub(crate) z: F,
pub x: F,
pub y: F,
pub z: F,
}
impl<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> GroupProjective<D, N, F> {
/// This is the point at infinity! This object really is the additive identity of the group,
/// when the group law is addition, which it is here. It satisfies the properties that
/// $zero+a=a$ for some $a$ in the group, as well as $a+(-a)=zero$, which means that the
/// convention zero makes the most sense to me here.
pub(crate) fn zero() -> Self {
pub fn zero() -> Self {
Self {
x: F::zero(),
y: F::one(),
z: F::zero(),
}
}
pub(crate) fn is_zero(&self) -> bool {

pub fn is_zero(&self) -> bool {
self.z.is_zero()
}

Expand All @@ -188,7 +188,7 @@ impl<const D: usize, const N: usize, F: FieldExtensionTrait<D, N>> GroupProjecti
/// Complexity:
/// `6M`(ultiplications) + `2S`(quarings)
/// + `1m`(ultiplication by scalar) + `9A`(dditions)
pub(crate) fn double(&self) -> Self {
pub fn double(&self) -> Self {
let t0 = self.y * self.y;
let z3 = t0 + t0;
let z3 = z3 + z3;
Expand Down
Loading

0 comments on commit 457dd08

Please sign in to comment.