Skip to content

Commit

Permalink
EC point serialization (#141)
Browse files Browse the repository at this point in the history
* refactor!: Compressed format for EC points

 - The bit flags for sign and identity have been fliped for
 curves with 2 spare bits: Bn256, Pluto and Eris.

* fix: bn test vectors

* fix: update new_impl_curve calls

* refactor! Uncompressed format for EC points

* add: unchecked sered test

* fix: review comments

add: uncompressed identity test

fix: uncompressed serialization

fix: cleanup

fix: review comments

add: compute spare bits from NUM_BITS

fix: strict flag decoding

fix: imports

add: check for the bits in 0 spare bits case

* fix: fip FLAG_BITS

* fix: make to_bytes constant time

* add: Econding format doc

* fix: typos

* chore: update encoding spec with explicit byte/bit position and endianess

* chore: Remove flags from uncompressed format

Modified the docs accordingly and rearranged x,y order.

---------

Co-authored-by: Eduard S <[email protected]>
  • Loading branch information
davidnevadoc and ed255 authored Mar 14, 2024
1 parent dc57ddd commit 1662f88
Show file tree
Hide file tree
Showing 9 changed files with 303 additions and 86 deletions.
4 changes: 2 additions & 2 deletions src/bn256/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::arithmetic::EndoParameters;
use crate::bn256::Fq;
use crate::bn256::Fq2;
use crate::bn256::Fr;
use crate::derive::curve::{IDENTITY_MASK, IDENTITY_SHIFT, SIGN_MASK, SIGN_SHIFT};
use crate::endo;
use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
Expand Down Expand Up @@ -32,7 +33,6 @@ new_curve_impl!(
(pub),
G1,
G1Affine,
false,
Fq,
Fr,
(G1_GENERATOR_X,G1_GENERATOR_Y),
Expand All @@ -46,7 +46,6 @@ new_curve_impl!(
(pub),
G2,
G2Affine,
false,
Fq2,
Fr,
(G2_GENERATOR_X, G2_GENERATOR_Y),
Expand Down Expand Up @@ -201,6 +200,7 @@ impl G1 {
#[cfg(test)]
mod test {
use super::*;
use group::UncompressedEncoding;
crate::curve_testing_suite!(G1, G2);
crate::curve_testing_suite!(G1, "hash_to_curve");
crate::curve_testing_suite!(G1, "endo_consistency");
Expand Down
10 changes: 5 additions & 5 deletions src/bn256/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ mod test {
let expected_results = [
"e0c5a6834e0329b4f8bdc91144b3e687ac9d810a8e899415267db9cfbf61e91e",
"7052a20bee99cbe054fdd8b2e336db3ed3e9a265229e44ab8197c5eabdef2b0b",
"2f058acc133957074ac79e9b9b1867a0cf3d13df7aa7de7f48e9a6be7d96aa6d",
"2f058acc133957074ac79e9b9b1867a0cf3d13df7aa7de7f48e9a6be7d96aaad",
"b2ff44a25693b811f35e33feb3e99ad9ba0d06425a3ffd5e79cef63d20143314",
"ab2f6d71d2fde51546d8a5782aa9f707e585b84644470f0c876784dbebd30c55",
"6a4e0e30f37a8d1b92b8cf08df3735a36b4937ee455a9dc5f9283a13530db144",
"f1c69be8c5f5f9e28b0e9f76ab77651a7dcaaae371fbba66450cbcee0ed5b16b",
"ab2f6d71d2fde51546d8a5782aa9f707e585b84644470f0c876784dbebd30c95",
"6a4e0e30f37a8d1b92b8cf08df3735a36b4937ee455a9dc5f9283a13530db184",
"f1c69be8c5f5f9e28b0e9f76ab77651a7dcaaae371fbba66450cbcee0ed5b1ab",
"e86267c2e3355d7a6f664a0ea71374406337d452a3f9a294a0594df53c08df21",
"03cf55ca983ecd8a2e2baae18d979d97d688a978d829701c66a14d7c4da58e62",
"03cf55ca983ecd8a2e2baae18d979d97d688a978d829701c66a14d7c4da58ea2",
"5302c2cfe3c909e9378d08c951bb33d0813818a1baf734379aac8aaa47f38f0d",
];

Expand Down
334 changes: 263 additions & 71 deletions src/derive/curve.rs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/grumpkin/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::arithmetic::mul_512;
use crate::arithmetic::sbb;
use crate::arithmetic::CurveEndo;
use crate::arithmetic::EndoParameters;
use crate::derive::curve::{IDENTITY_MASK, IDENTITY_SHIFT, SIGN_MASK, SIGN_SHIFT};
use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
use crate::group::Curve;
Expand Down Expand Up @@ -29,7 +30,6 @@ new_curve_impl!(
(pub),
G1,
G1Affine,
false,
Fq,
Fr,
(G1_GENERATOR_X, G1_GENERATOR_Y),
Expand Down Expand Up @@ -92,6 +92,7 @@ impl G1 {
#[cfg(test)]
mod test {
use super::*;
use group::UncompressedEncoding;
crate::curve_testing_suite!(G1);
crate::curve_testing_suite!(G1, "endo_consistency");
crate::curve_testing_suite!(G1, "endo");
Expand Down
5 changes: 2 additions & 3 deletions src/pluto_eris/curve.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::fields::{fp::Fp, fp2::Fp2, fq::Fq};
use crate::derive::curve::{IDENTITY_MASK, IDENTITY_SHIFT, SIGN_MASK, SIGN_SHIFT};
use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
use crate::group::{prime::PrimeCurveAffine, Curve, Group as _, GroupEncoding};
Expand Down Expand Up @@ -124,7 +125,6 @@ new_curve_impl!(
(pub),
G1,
G1Affine,
false,
Fp,
Fq,
(G1_GENERATOR_X,G1_GENERATOR_Y),
Expand Down Expand Up @@ -160,7 +160,6 @@ new_curve_impl!(
(pub),
Eris,
ErisAffine,
false,
Fq,
Fp,
(ERIS_GENERATOR_X,ERIS_GENERATOR_Y),
Expand Down Expand Up @@ -232,7 +231,6 @@ new_curve_impl!(
(pub),
G2,
G2Affine,
false,
Fp2,
Fq,
(G2_GENERATOR_X,G2_GENERATOR_Y),
Expand All @@ -245,6 +243,7 @@ new_curve_impl!(
#[cfg(test)]
mod test {
use super::*;
use group::UncompressedEncoding;
crate::curve_testing_suite!(G1, Eris, G2);
crate::curve_testing_suite!(G1, Eris, "hash_to_curve");
crate::curve_testing_suite!(G1, Eris, "endo_consistency");
Expand Down
4 changes: 2 additions & 2 deletions src/secp256k1/curve.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::derive::curve::{IDENTITY_MASK, IDENTITY_SHIFT, SIGN_MASK, SIGN_SHIFT};
use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
use crate::group::{prime::PrimeCurveAffine, Curve, Group as _, GroupEncoding};
Expand Down Expand Up @@ -58,7 +59,6 @@ new_curve_impl!(
(pub),
Secp256k1,
Secp256k1Affine,
true,
Fp,
Fq,
(SECP_GENERATOR_X,SECP_GENERATOR_Y),
Expand Down Expand Up @@ -127,7 +127,6 @@ new_curve_impl!(
(pub(crate)),
IsoSecp256k1,
IsoSecp256k1Affine,
true,
Fp,
Fq,
(ISO_SECP_GENERATOR_X, ISO_SECP_GENERATOR_Y),
Expand Down Expand Up @@ -271,6 +270,7 @@ pub(crate) fn iso_map_secp256k1(rp: IsoSecp256k1) -> Secp256k1 {
#[cfg(test)]
mod test {
use super::*;
use group::UncompressedEncoding;
crate::curve_testing_suite!(Secp256k1);
crate::curve_testing_suite!(Secp256k1, "endo_consistency");
crate::curve_testing_suite!(Secp256k1, "ecdsa_example");
Expand Down
3 changes: 2 additions & 1 deletion src/secp256r1/curve.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::derive::curve::{IDENTITY_MASK, IDENTITY_SHIFT, SIGN_MASK, SIGN_SHIFT};
use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
use crate::group::{prime::PrimeCurveAffine, Curve, Group as _, GroupEncoding};
Expand Down Expand Up @@ -69,7 +70,6 @@ new_curve_impl!(
(pub),
Secp256r1,
Secp256r1Affine,
true,
Fp,
Fq,
(SECP_GENERATOR_X,SECP_GENERATOR_Y),
Expand All @@ -94,6 +94,7 @@ impl Secp256r1 {
#[cfg(test)]
mod test {
use super::*;
use group::UncompressedEncoding;
crate::curve_testing_suite!(Secp256r1);
crate::curve_testing_suite!(Secp256r1, "ecdsa_example");
crate::curve_testing_suite!(
Expand Down
3 changes: 2 additions & 1 deletion src/secq256k1/curve.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::derive::curve::{IDENTITY_MASK, IDENTITY_SHIFT, SIGN_MASK, SIGN_SHIFT};
use crate::ff::WithSmallOrderMulGroup;
use crate::ff::{Field, PrimeField};
use crate::group::Curve;
Expand Down Expand Up @@ -41,7 +42,6 @@ new_curve_impl!(
(pub),
Secq256k1,
Secq256k1Affine,
true,
Fq,
Fp,
(SECQ_GENERATOR_X, SECQ_GENERATOR_Y),
Expand Down Expand Up @@ -74,6 +74,7 @@ impl Secq256k1 {
#[cfg(test)]
mod test {
use super::*;
use group::UncompressedEncoding;
crate::curve_testing_suite!(Secq256k1);
crate::curve_testing_suite!(Secq256k1, "endo_consistency");
crate::curve_testing_suite!(
Expand Down
23 changes: 23 additions & 0 deletions src/tests/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,29 +238,51 @@ macro_rules! curve_testing_suite {
.unwrap()
.is_identity()
));

assert!(bool::from(
<$c as CurveExt>::AffineExt::from_uncompressed(&<$c as CurveExt>::AffineExt::identity().to_uncompressed())
.unwrap()
.is_identity()
));

assert!(bool::from(
<$c as CurveExt>::AffineExt::from_bytes(&<$c as CurveExt>::AffineExt::identity().to_bytes())
.unwrap()
.is_identity()
));

for _ in 0..100 {
let projective_point = $c::random(OsRng);
let affine_point: <$c as CurveExt>::AffineExt = projective_point.into();

// Compressed format tests
let projective_repr = projective_point.to_bytes();
let affine_repr = affine_point.to_bytes();

let projective_point_rec = $c::from_bytes(&projective_repr).unwrap();
let projective_point_rec_unchecked = $c::from_bytes(&projective_repr).unwrap();

let affine_point_rec = <$c as CurveExt>::AffineExt::from_bytes(&affine_repr).unwrap();
let affine_point_rec_unchecked = <$c as CurveExt>::AffineExt::from_bytes(&affine_repr).unwrap();

assert_eq!(projective_point, projective_point_rec);
assert_eq!(projective_point, projective_point_rec_unchecked);
assert_eq!(affine_point, affine_point_rec);
assert_eq!(affine_point, affine_point_rec_unchecked);

// Uncompressed format
let affine_repr = affine_point.to_uncompressed();

let affine_point_rec = <$c as CurveExt>::AffineExt::from_uncompressed_unchecked(&affine_repr).unwrap();
let affine_point_rec_unchecked = <$c as CurveExt>::AffineExt::from_uncompressed_unchecked(&affine_repr).unwrap();

assert_eq!(affine_point, affine_point_rec);
assert_eq!(affine_point, affine_point_rec_unchecked);
}
}
}

// TODO Change name
macro_rules! random_serialization_test {
($c: ident) => {
for _ in 0..100 {
Expand Down Expand Up @@ -327,6 +349,7 @@ macro_rules! curve_testing_suite {
use crate::{CurveAffine, CurveExt};
use rand_core::OsRng;


#[test]
fn test_curve() {
$(
Expand Down

0 comments on commit 1662f88

Please sign in to comment.