tiny_curve/
curve32.rs

1use primeorder::{
2    elliptic_curve::{
3        bigint::U64, generic_array::typenum, Curve, CurveArithmetic, FieldBytes, FieldBytesEncoding,
4    },
5    point_arithmetic::EquationAIsMinusThree,
6    AffinePoint, PrimeCurve, PrimeCurveParams, ProjectivePoint,
7};
8
9use crate::{
10    prime_field::FieldElement,
11    traits::{Modulus, PrimeFieldConstants},
12};
13
14const ORDER: u64 = 0xffff0f07;
15const FIELD_MODULUS: u64 = 0xffffff67;
16
17impl PrimeFieldConstants<u32> for Modulus<u32, FIELD_MODULUS> {
18    type Repr = FieldBytes<TinyCurve32>;
19    const MODULUS_STR: &'static str = "0xffffff67";
20    const MODULUS: u32 = FIELD_MODULUS as u32;
21    const NUM_BITS: u32 = 32;
22    const CAPACITY: u32 = 31;
23    const TWO_INV: u32 = 0x7fffffb4;
24    const MULTIPLICATIVE_GENERATOR: u32 = 3;
25    const S: u32 = 1;
26    const ROOT_OF_UNITY: u32 = 0xffffff66;
27    const ROOT_OF_UNITY_INV: u32 = 0xffffff66;
28    const DELTA: u32 = 9;
29}
30
31impl PrimeFieldConstants<u32> for Modulus<u32, ORDER> {
32    type Repr = FieldBytes<TinyCurve32>;
33    const MODULUS_STR: &'static str = "0xffff0f07";
34    const MODULUS: u32 = ORDER as u32;
35    const NUM_BITS: u32 = 32;
36    const CAPACITY: u32 = 31;
37    const TWO_INV: u32 = 0x7fff8784;
38    const MULTIPLICATIVE_GENERATOR: u32 = 3;
39    const S: u32 = 1;
40    const ROOT_OF_UNITY: u32 = 0xffff0f06;
41    const ROOT_OF_UNITY_INV: u32 = 0xffff0f06;
42    const DELTA: u32 = 9;
43}
44
45/// An elliptic curve with a 32-bit order.
46#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
47pub struct TinyCurve32;
48
49impl Curve for TinyCurve32 {
50    type FieldBytesSize = typenum::U8;
51    type Uint = U64;
52    const ORDER: Self::Uint = Self::Uint::from_u64(ORDER);
53}
54
55impl FieldBytesEncoding<TinyCurve32> for <TinyCurve32 as Curve>::Uint {}
56
57impl CurveArithmetic for TinyCurve32 {
58    type Scalar = FieldElement<u32, ORDER>;
59    type AffinePoint = AffinePoint<Self>;
60    type ProjectivePoint = ProjectivePoint<Self>;
61}
62
63impl PrimeCurve for TinyCurve32 {}
64
65impl PrimeCurveParams for TinyCurve32 {
66    type FieldElement = FieldElement<u32, FIELD_MODULUS>;
67    type PointArithmetic = EquationAIsMinusThree;
68
69    const EQUATION_A: Self::FieldElement = FieldElement::new_unchecked(FIELD_MODULUS as u32 - 3);
70    const EQUATION_B: Self::FieldElement = FieldElement::new_unchecked(8);
71    const GENERATOR: (Self::FieldElement, Self::FieldElement) = (
72        FieldElement::new_unchecked(4274000713),
73        FieldElement::new_unchecked(443355223),
74    );
75}
76
77#[cfg(test)]
78mod tests {
79    use super::TinyCurve32;
80    use primeorder::elliptic_curve::{
81        bigint::U64,
82        ops::{MulByGenerator, Reduce},
83        CurveArithmetic, ProjectivePoint,
84    };
85    use proptest::prelude::*;
86
87    type Scalar = <TinyCurve32 as CurveArithmetic>::Scalar;
88    type Point = ProjectivePoint<TinyCurve32>;
89
90    prop_compose! {
91        /// Generate a random odd modulus.
92        fn scalar()(n in any::<u64>()) -> Scalar {
93            Scalar::reduce(U64::from(n))
94        }
95    }
96
97    proptest! {
98        #[test]
99        fn mul_by_generator(x in scalar(), y in scalar()) {
100            let p1 = Point::mul_by_generator(&x) + Point::mul_by_generator(&y);
101            let p2 = Point::mul_by_generator(&(x + y));
102            assert_eq!(p1, p2);
103        }
104    }
105}
106
107#[cfg(test)]
108mod tests_scalar {
109    use primeorder::{elliptic_curve::CurveArithmetic, Field, PrimeField};
110
111    use super::TinyCurve32;
112
113    type F = <TinyCurve32 as CurveArithmetic>::Scalar;
114
115    primeorder::impl_field_identity_tests!(F);
116    primeorder::impl_field_invert_tests!(F);
117    primeorder::impl_field_sqrt_tests!(F);
118
119    // t = (modulus - 1) >> S
120    const T: [u64; 1] = [(F::MODULUS - 1) as u64 >> F::S];
121    primeorder::impl_primefield_tests!(F, T);
122}
123
124#[cfg(test)]
125mod tests_field_element {
126    use primeorder::{Field, PrimeCurveParams, PrimeField};
127
128    use super::TinyCurve32;
129
130    type F = <TinyCurve32 as PrimeCurveParams>::FieldElement;
131
132    primeorder::impl_field_identity_tests!(F);
133    primeorder::impl_field_invert_tests!(F);
134    primeorder::impl_field_sqrt_tests!(F);
135
136    // t = (modulus - 1) >> S
137    const T: [u64; 1] = [(F::MODULUS - 1) as u64 >> F::S];
138    primeorder::impl_primefield_tests!(F, T);
139}