Compare commits
5 Commits
5b4abfec91
...
c14b406197
Author | SHA1 | Date |
---|---|---|
Luke Parker | c14b406197 | |
str4d | df67e299e6 | |
Jack Grigg | 43598cf303 | |
Luke Parker | a46b5be95c | |
Luke Parker | f89331c06e |
|
@ -49,6 +49,7 @@ group = { version = "0.13", default-features = false }
|
||||||
rand = { version = "0.8", default-features = false }
|
rand = { version = "0.8", default-features = false }
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
subtle = { version = "2.3", default-features = false }
|
subtle = { version = "2.3", default-features = false }
|
||||||
|
zeroize = { version = "^1.5", default-features = false, features = ["derive"] }
|
||||||
|
|
||||||
# alloc dependencies
|
# alloc dependencies
|
||||||
blake2b_simd = { version = "1", optional = true, default-features = false }
|
blake2b_simd = { version = "1", optional = true, default-features = false }
|
||||||
|
|
|
@ -4,6 +4,12 @@ This crate provides an implementation of the Pasta elliptic curve constructions,
|
||||||
Pallas and Vesta. More details about the Pasta curves can be found
|
Pallas and Vesta. More details about the Pasta curves can be found
|
||||||
[in this blog post](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/).
|
[in this blog post](https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/).
|
||||||
|
|
||||||
|
## RFC process
|
||||||
|
|
||||||
|
This crate follows the [zkcrypto RFC process](https://zkcrypto.github.io/rfcs/).
|
||||||
|
If you want to propose "substantial" changes to this crate, please
|
||||||
|
[create an RFC](https://github.com/zkcrypto/rfcs) for wider discussion.
|
||||||
|
|
||||||
## [Documentation](https://docs.rs/pasta_curves)
|
## [Documentation](https://docs.rs/pasta_curves)
|
||||||
|
|
||||||
## Minimum Supported Rust Version
|
## Minimum Supported Rust Version
|
||||||
|
|
116
src/curves.rs
116
src/curves.rs
|
@ -30,7 +30,7 @@ macro_rules! new_curve_impl {
|
||||||
(($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident,
|
(($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident,
|
||||||
$curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => {
|
$curve_id:literal, $a_raw:expr, $b_raw:expr, $curve_type:ident) => {
|
||||||
/// Represents a point in the projective coordinate space.
|
/// Represents a point in the projective coordinate space.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, zeroize::Zeroize)]
|
||||||
#[cfg_attr(feature = "repr-c", repr(C))]
|
#[cfg_attr(feature = "repr-c", repr(C))]
|
||||||
$($privacy)* struct $name {
|
$($privacy)* struct $name {
|
||||||
x: $base,
|
x: $base,
|
||||||
|
@ -466,32 +466,41 @@ macro_rules! new_curve_impl {
|
||||||
type Output = $name;
|
type Output = $name;
|
||||||
|
|
||||||
fn mul(self, other: &'b $scalar) -> Self::Output {
|
fn mul(self, other: &'b $scalar) -> Self::Output {
|
||||||
// TODO: make this faster
|
// Create a table out of the point
|
||||||
|
// TODO: This can be made more efficient with a 5-bit window
|
||||||
let mut acc = $name::identity();
|
let mut arr = [$name::identity(); 16];
|
||||||
|
arr[1] = *self;
|
||||||
// This is a simple double-and-add implementation of point
|
for i in 2 .. 16 {
|
||||||
// multiplication, moving from most significant to least
|
arr[i] = if (i % 2) == 0 {
|
||||||
// significant bit of the scalar.
|
arr[i / 2].double()
|
||||||
//
|
} else {
|
||||||
// We don't use `PrimeFieldBits::.to_le_bits` here, because that would
|
arr[i - 1] + arr[1]
|
||||||
// force users of this crate to depend on `bitvec` where they otherwise
|
};
|
||||||
// might not need to.
|
|
||||||
//
|
|
||||||
// NOTE: We skip the leading bit because it's always unset (we are turning
|
|
||||||
// the 32-byte repr into 256 bits, and $scalar::NUM_BITS = 255).
|
|
||||||
for bit in other
|
|
||||||
.to_repr()
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
|
|
||||||
.skip(1)
|
|
||||||
{
|
|
||||||
acc = acc.double();
|
|
||||||
acc = $name::conditional_select(&acc, &(acc + self), bit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
acc
|
let mut res = $name::identity();
|
||||||
|
let mut first = true;
|
||||||
|
// Iterate from significant byte to least significant byte
|
||||||
|
for byte in other.to_repr().iter().rev() {
|
||||||
|
// Shift the result over 4 bits
|
||||||
|
if !first {
|
||||||
|
for _ in 0 .. 4 {
|
||||||
|
res = res.double();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
// Add the top-nibble from this byte into the result
|
||||||
|
res += arr[usize::from(byte >> 4)];
|
||||||
|
// Shift the result over
|
||||||
|
for _ in 0 .. 4 {
|
||||||
|
res = res.double();
|
||||||
|
}
|
||||||
|
// Add the bottom-nibble from this byte into the result
|
||||||
|
res += arr[usize::from(byte & 0b1111)];
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,32 +590,41 @@ macro_rules! new_curve_impl {
|
||||||
type Output = $name;
|
type Output = $name;
|
||||||
|
|
||||||
fn mul(self, other: &'b $scalar) -> Self::Output {
|
fn mul(self, other: &'b $scalar) -> Self::Output {
|
||||||
// TODO: make this faster
|
// Create a table out of the point
|
||||||
|
// TODO: This can be made more efficient with a 5-bit window
|
||||||
let mut acc = $name::identity();
|
let mut arr = [$name::identity(); 16];
|
||||||
|
arr[1] = (*self).into();
|
||||||
// This is a simple double-and-add implementation of point
|
for i in 2 .. 16 {
|
||||||
// multiplication, moving from most significant to least
|
arr[i] = if (i % 2) == 0 {
|
||||||
// significant bit of the scalar.
|
arr[i / 2].double()
|
||||||
//
|
} else {
|
||||||
// We don't use `PrimeFieldBits::.to_le_bits` here, because that would
|
arr[i - 1] + arr[1]
|
||||||
// force users of this crate to depend on `bitvec` where they otherwise
|
};
|
||||||
// might not need to.
|
|
||||||
//
|
|
||||||
// NOTE: We skip the leading bit because it's always unset (we are turning
|
|
||||||
// the 32-byte repr into 256 bits, and $scalar::NUM_BITS = 255).
|
|
||||||
for bit in other
|
|
||||||
.to_repr()
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.flat_map(|byte| (0..8).rev().map(move |i| Choice::from((byte >> i) & 1u8)))
|
|
||||||
.skip(1)
|
|
||||||
{
|
|
||||||
acc = acc.double();
|
|
||||||
acc = $name::conditional_select(&acc, &(acc + self), bit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
acc
|
let mut res = $name::identity();
|
||||||
|
let mut first = true;
|
||||||
|
// Iterate from significant byte to least significant byte
|
||||||
|
for byte in other.to_repr().iter().rev() {
|
||||||
|
// Shift the result over 4 bits
|
||||||
|
if !first {
|
||||||
|
for _ in 0 .. 4 {
|
||||||
|
res = res.double();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
// Add the top-nibble from this byte into the result
|
||||||
|
res += arr[usize::from(byte >> 4)];
|
||||||
|
// Shift the result over
|
||||||
|
for _ in 0 .. 4 {
|
||||||
|
res = res.double();
|
||||||
|
}
|
||||||
|
// Add the bottom-nibble from this byte into the result
|
||||||
|
res += arr[usize::from(byte & 0b1111)];
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::arithmetic::SqrtTables;
|
||||||
// The internal representation of this type is four 64-bit unsigned
|
// The internal representation of this type is four 64-bit unsigned
|
||||||
// integers in little-endian order. `Fp` values are always in
|
// integers in little-endian order. `Fp` values are always in
|
||||||
// Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256.
|
// Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256.
|
||||||
#[derive(Clone, Copy, Eq)]
|
#[derive(Clone, Copy, Eq, zeroize::Zeroize)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Fp(pub(crate) [u64; 4]);
|
pub struct Fp(pub(crate) [u64; 4]);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::arithmetic::SqrtTables;
|
||||||
// The internal representation of this type is four 64-bit unsigned
|
// The internal representation of this type is four 64-bit unsigned
|
||||||
// integers in little-endian order. `Fq` values are always in
|
// integers in little-endian order. `Fq` values are always in
|
||||||
// Montgomery form; i.e., Fq(a) = aR mod q, with R = 2^256.
|
// Montgomery form; i.e., Fq(a) = aR mod q, with R = 2^256.
|
||||||
#[derive(Clone, Copy, Eq)]
|
#[derive(Clone, Copy, Eq, zeroize::Zeroize)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Fq(pub(crate) [u64; 4]);
|
pub struct Fq(pub(crate) [u64; 4]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue