This crate provides basic cryptographic implementation as in Field
, Curve
and Pairing
, Fft
, Kzg
, and also supports fully no_std
and parity-scale-codec
.
Cryptography libraries need to be applied optimization easily because computation cost affects users waiting time and on-chain gas cost. We design this library following two perspectives.
We divide arithmetic operation and interface. Arithmetic operation is concrete logic as in elliptic curve addition and so on, and the interface is trait cryptography primitive supports. And we combine them with macro. With this design, we can keep the finite field and elliptic curve implementation simple.
Fft Field
, Pairing Field
and so on.arithmetic
and behave
together.The following Fr
support four basic operation.
```rust use zkstd::common::; use zkstd::behave::; use zkstd::dress::field::; use zkstd::arithmetic::bits_256::; use serde::{Deserialize, Serialize};
pub struct Fr(pub [u64; 4]);
const MODULUS: [u64; 4] = [ 0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48, ];
/// Generator of the Scalar field pub const MULTIPLICATIVE_GENERATOR: Fr = Fr([7, 0, 0, 0]);
const GENERATOR: [u64; 4] = [ 0x0000000efffffff1, 0x17e363d300189c0f, 0xff9c57876f8457b0, 0x351332208fc5a8c4, ];
/// R = 2^256 mod r const R: [u64; 4] = [ 0x00000001fffffffe, 0x5884b7fa00034802, 0x998c4fefecbc4ff5, 0x1824b159acc5056f, ];
/// R^2 = 2^512 mod r const R2: [u64; 4] = [ 0xc999e990f3f29c6d, 0x2b6cedcb87925c23, 0x05d314967254398f, 0x0748d9d99f59ff11, ];
/// R^3 = 2^768 mod r const R3: [u64; 4] = [ 0xc62c1807439b73af, 0x1b3e0d188cf06990, 0x73d13c71c7b5f418, 0x6e2a5bb9c8db33e9, ];
pub const INV: u64 = 0xfffffffeffffffff;
const S: usize = 32;
pub const ROOTOFUNITY: Fr = Fr([ 0xb9b58d8c5f0e466a, 0x5b1b4c801819d7ec, 0x0af53ae352a31e64, 0x5bf3adda19e9b27b, ]);
impl Fr { pub(crate) const fn montgomery_reduce(self) -> [u64; 4] { mont( [self.0[0], self.0[1], self.0[2], self.0[3], 0, 0, 0, 0], MODULUS, INV, ) } }
fftfieldoperation!( Fr, MODULUS, GENERATOR, MULTIPLICATIVEGENERATOR, INV, ROOTOF_UNITY, R, R2, R3, S );
mod tests { use super::*; use paste::paste; use rand_core::OsRng;
field_test!(bls12_381_scalar, Fr, 1000);
} ```
The following G1Affine
and G1Projective
supports point arithmetic.
```rust use zerojubjub::Fp; use serde::{Deserialize, Serialize}; use zerobls12_381::Fr; use zkstd::arithmetic::edwards::; use zkstd::common::; use zkstd::dress::curve::edwards::*;
pub const EDWARDSD: Fr = Fr::tomont_form([ 0x01065fd6d6343eb1, 0x292d7f6d37579d26, 0xf5fd9207e6bd7fd4, 0x2a9318e74bfa2b48, ]);
const X: Fr = Fr::tomontform([ 0x4df7b7ffec7beaca, 0x2e3ebb21fd6c54ed, 0xf1fbf02d0fd6cce6, 0x3fd2814c43ac65a6, ]);
const Y: Fr = Fr::tomontform([ 0x0000000000000012, 000000000000000000, 000000000000000000, 000000000000000000, ]);
const T: Fr = Fr::tomontform([ 0x07b6af007a0b6822b, 0x04ebe6448d1acbcb8, 0x036ae4ae2c669cfff, 0x0697235704b95be33, ]);
pub struct JubjubAffine { x: Fr, y: Fr, }
impl Add for JubjubAffine { type Output = JubjubExtended;
fn add(self, rhs: JubjubAffine) -> Self::Output {
add_point(self.to_extended(), rhs.to_extended())
}
}
impl Neg for JubjubAffine { type Output = Self;
fn neg(self) -> Self {
Self {
x: -self.x,
y: self.y,
}
}
}
impl Sub for JubjubAffine { type Output = JubjubExtended;
fn sub(self, rhs: JubjubAffine) -> Self::Output {
add_point(self.to_extended(), rhs.neg().to_extended())
}
}
impl Mul
fn mul(self, rhs: Fr) -> Self::Output {
scalar_point(self.to_extended(), &rhs)
}
}
impl Mul
fn mul(self, rhs: JubjubAffine) -> Self::Output {
scalar_point(rhs.to_extended(), &self)
}
}
impl JubjubAffine {
/// Constructs an JubJubAffine given x
and y
without checking
/// that the point is on the curve.
pub const fn fromrawunchecked(x: Fr, y: Fr) -> JubjubAffine {
JubjubAffine { x, y }
}
}
pub struct JubjubExtended { x: Fr, y: Fr, t: Fr, z: Fr, }
impl Add for JubjubExtended { type Output = JubjubExtended;
fn add(self, rhs: JubjubExtended) -> Self::Output {
add_point(self, rhs)
}
}
impl Neg for JubjubExtended { type Output = Self;
fn neg(self) -> Self {
Self {
x: -self.x,
y: self.y,
t: -self.t,
z: self.z,
}
}
}
impl Sub for JubjubExtended { type Output = JubjubExtended;
fn sub(self, rhs: JubjubExtended) -> Self::Output {
add_point(self, rhs.neg())
}
}
impl Mul
fn mul(self, rhs: Fr) -> Self::Output {
scalar_point(self, &rhs)
}
}
impl Mul
fn mul(self, rhs: JubjubExtended) -> Self::Output {
scalar_point(rhs, &self)
}
}
twistededwardscurveoperation!(Fr, Fr, EDWARDSD, JubjubAffine, JubjubExtended, X, Y, T);
mod tests { #[allow(unused_imports)] use super::; use zkstd::dress::curve::weierstrass::;
curve_test!(bls12_381, Fr, G1Affine, G1Projective, 100);
} ```
shell
$ cargo test