Skip to content

Commit 1622e83

Browse files
add support for T-256 curve (#197)
* add T-256 curve * update README * move comment up * make it no-std compat --------- Co-authored-by: guorong009 <[email protected]>
1 parent 382f405 commit 1622e83

File tree

5 files changed

+193
-2
lines changed

5 files changed

+193
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This library provides efficient and flexible implementations of various halo2-fr
1212

1313
The implementations were originally ported from [matterlabs/pairing](https://github.com/matter-labs/pairing/tree/master/src/bn256) and [zkcrypto/bls12-381](https://github.com/zkcrypto/bls12_381), but have been extended and optimized to cover a broader set of curves and use cases. Since its initial release, the library has expanded to include additional curves, along with the following features:
1414

15-
* `secp256k1`, `secp256r1`, `pluto`, `eris` and `grumpkin` curves, enhancing its usability across a range of cryptographic protocols.
15+
* `secp256k1`, `secp256r1`, `pluto`, `eris`, `T-256`, and `grumpkin` curves, enhancing its usability across a range of cryptographic protocols.
1616
* Assembly optimizations leading to significantly improved performance.
1717
* Various features related to serialization and deserialization of curve points and field elements.
1818
* Curve-specific optimizations and benchmarking capabilities.
@@ -59,4 +59,4 @@ The library's top-level directories are organized as follows:
5959

6060
* `benches`: Contains benchmarking tests.
6161
* `script`: Contains utility scripts.
62-
* `src`: Contains the source code of the library, further subdivided into modules for each supported curve (`bn256`, `grumpkin`, `secp256k1`, `secp256r1`, `secq256k1`, `pasta`, `pluto`, `eris`) and additional functionalities (`derive`, `tests`).
62+
* `src`: Contains the source code of the library, further subdivided into modules for each supported curve (`bn256`, `grumpkin`, `secp256k1`, `secp256r1`, `secq256k1`, `pasta`, `pluto`, `eris`, `t256`) and additional functionalities (`derive`, `tests`).

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub mod pluto_eris;
1616
pub mod secp256k1;
1717
pub mod secp256r1;
1818
pub mod secq256k1;
19+
pub mod t256;
1920

2021
#[macro_use]
2122
mod derive;

src/t256/curve.rs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#[cfg(not(feature = "std"))]
2+
extern crate alloc;
3+
#[cfg(not(feature = "std"))]
4+
use alloc::{boxed::Box, vec::Vec};
5+
6+
use core::{
7+
cmp,
8+
fmt::Debug,
9+
iter::Sum,
10+
ops::{Add, Mul, Neg, Sub},
11+
};
12+
13+
use rand_core::RngCore;
14+
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
15+
16+
use crate::{
17+
ff::{Field, PrimeField, WithSmallOrderMulGroup},
18+
group::{prime::PrimeCurveAffine, Curve, Group as _, GroupEncoding},
19+
t256::{Fp, Fq},
20+
Coordinates, CurveAffine, CurveExt,
21+
};
22+
23+
impl group::cofactor::CofactorGroup for T256 {
24+
type Subgroup = T256;
25+
26+
fn clear_cofactor(&self) -> Self {
27+
*self
28+
}
29+
30+
fn into_subgroup(self) -> CtOption<Self::Subgroup> {
31+
CtOption::new(self, 1.into())
32+
}
33+
34+
fn is_torsion_free(&self) -> Choice {
35+
1.into()
36+
}
37+
}
38+
39+
// We take these parameters from: https://github.com/pag-crypto/sigpop/blob/eb7ea5914e8303b5484fe5bb8d200d08345a46c6/circ_fields/src/t256/curves/mod.rs
40+
// Generator (x = 5, y as in sigpop)
41+
const T256_GENERATOR_X: Fp = Fp::from_raw([
42+
0x0000000000000005,
43+
0x0000000000000000,
44+
0x0000000000000000,
45+
0x0000000000000000,
46+
]);
47+
48+
const T256_GENERATOR_Y: Fp = Fp::from_raw([
49+
0x5826108A653DE28D,
50+
0x0ED60B9E33CE397C,
51+
0x5EFC7B55F6B24FBE,
52+
0x3E86C0CFEBF2C716,
53+
]);
54+
55+
// a = p − 3
56+
const T256_A: Fp = Fp::from_raw([
57+
0x93135661B1C4B114,
58+
0x7E72B42B30E73177,
59+
0x0000000000000001,
60+
0xFFFFFFFF00000001,
61+
]);
62+
63+
// b = 0xB441071B12F4A0366FB552F8E21ED4AC36B06ACEEB354224863E60F20219FC56
64+
const T256_B: Fp = Fp::from_raw([
65+
0x863E60F20219FC56,
66+
0x36B06ACEEB354224,
67+
0x6FB552F8E21ED4AC,
68+
0xB441071B12F4A036,
69+
]);
70+
71+
use crate::{
72+
impl_binops_additive, impl_binops_additive_specify_output, impl_binops_multiplicative,
73+
impl_binops_multiplicative_mixed, new_curve_impl,
74+
};
75+
76+
new_curve_impl!(
77+
(pub),
78+
T256,
79+
T256Affine,
80+
Fp,
81+
Fq,
82+
(T256_GENERATOR_X,T256_GENERATOR_Y),
83+
T256_A,
84+
T256_B,
85+
"t256",
86+
|domain_prefix| hash_to_curve(domain_prefix, hash_to_curve_suite(b"T256_XMD:SHA-256_SSWU_RO_")),
87+
crate::serde::CompressedFlagConfig::Extra,
88+
standard_sign
89+
);
90+
91+
fn hash_to_curve_suite(domain: &[u8]) -> crate::hash_to_curve::Suite<T256, sha2::Sha256, 48> {
92+
// Z : <https://datatracker.ietf.org/doc/html/rfc9380#sswu-z-code>
93+
// Z = -2
94+
const SSWU_Z: Fp = Fp::from_raw([
95+
0x93135661B1C4B115,
96+
0x7E72B42B30E73177,
97+
0x0000000000000001,
98+
0xFFFFFFFF00000001,
99+
]);
100+
101+
let iso_map = crate::hash_to_curve::Iso {
102+
a: T256::a(),
103+
b: T256::b(),
104+
map: Box::new(move |x, y, z| T256 { x, y, z }),
105+
};
106+
107+
crate::hash_to_curve::Suite::new(domain, SSWU_Z, crate::hash_to_curve::Method::SSWU(iso_map))
108+
}
109+
110+
#[allow(clippy::type_complexity)]
111+
pub(crate) fn hash_to_curve<'a>(
112+
domain_prefix: &'a str,
113+
suite: crate::hash_to_curve::Suite<T256, sha2::Sha256, 48>,
114+
) -> Box<dyn Fn(&[u8]) -> T256 + 'a> {
115+
Box::new(move |message| suite.hash_to_curve(domain_prefix, message))
116+
}
117+
118+
#[cfg(test)]
119+
mod test {
120+
use group::UncompressedEncoding;
121+
use rand_core::OsRng;
122+
123+
use super::*;
124+
use crate::serde::SerdeObject;
125+
crate::curve_testing_suite!(T256);
126+
crate::curve_testing_suite!(T256, "ecdsa_example");
127+
crate::curve_testing_suite!(
128+
T256,
129+
"constants",
130+
Fp::MODULUS,
131+
T256_A,
132+
T256_B,
133+
T256_GENERATOR_X,
134+
T256_GENERATOR_Y,
135+
Fq::MODULUS
136+
);
137+
}

src/t256/fp.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#[cfg(not(feature = "std"))]
2+
extern crate alloc;
3+
#[cfg(not(feature = "std"))]
4+
use alloc::vec::Vec;
5+
6+
use core::convert::TryInto;
7+
8+
use halo2derive::impl_field;
9+
use rand_core::RngCore;
10+
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
11+
12+
impl_field!(
13+
t256_base,
14+
Fp,
15+
modulus = "ffffffff0000000100000000000000017e72b42b30e7317793135661b1c4b117",
16+
mul_gen = "6",
17+
zeta = "b6e848ab29fcd1fa4bdd4681fd4839c7bce2889d6b27546299d130ed370be14d",
18+
from_uniform = [48, 64],
19+
endian = "big",
20+
);
21+
22+
crate::extend_field_legendre!(Fp);
23+
crate::impl_binops_calls!(Fp);
24+
crate::impl_binops_additive!(Fp, Fp);
25+
crate::impl_binops_multiplicative!(Fp, Fp);
26+
crate::field_bits!(Fp);
27+
crate::serialize_deserialize_primefield!(Fp);
28+
crate::impl_from_u64!(Fp);
29+
crate::impl_from_bool!(Fp);
30+
31+
#[cfg(test)]
32+
mod test {
33+
use super::Fp;
34+
use crate::{
35+
arith_test, constants_test, from_uniform_bytes_test, legendre_test, serde_test, test,
36+
};
37+
38+
constants_test!(Fp);
39+
40+
arith_test!(Fp);
41+
legendre_test!(Fp);
42+
test!(arith, Fp, sqrt_test, 1000);
43+
44+
serde_test!(Fp PrimeFieldBits);
45+
from_uniform_bytes_test!(Fp, 1000, L 64, L 48);
46+
}

src/t256/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
mod curve;
2+
mod fp;
3+
4+
// the base field of secp256r1 is Fq
5+
pub use crate::secp256r1::Fp as Fq;
6+
pub use curve::*;
7+
pub use fp::*;

0 commit comments

Comments
 (0)