openvm_ecc_guest/
p256.rs

1use core::ops::{Add, Neg};
2
3use hex_literal::hex;
4#[cfg(not(target_os = "zkvm"))]
5use lazy_static::lazy_static;
6#[cfg(not(target_os = "zkvm"))]
7use num_bigint::BigUint;
8use openvm_algebra_guest::{Field, IntMod};
9
10use super::group::{CyclicGroup, Group};
11use crate::weierstrass::{CachedMulTable, IntrinsicCurve};
12
13#[cfg(not(target_os = "zkvm"))]
14lazy_static! {
15    // The constants are taken from: https://neuromancer.sk/std/secg/secp256r1
16    pub static ref P256_MODULUS: BigUint = BigUint::from_bytes_be(&hex!(
17        "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"
18    ));
19    pub static ref P256_ORDER: BigUint = BigUint::from_bytes_be(&hex!(
20        "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"
21    ));
22}
23
24openvm_algebra_moduli_macros::moduli_declare! {
25    P256Coord { modulus = "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff" },
26    P256Scalar { modulus = "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" },
27}
28
29pub const P256_NUM_LIMBS: usize = 32;
30pub const P256_LIMB_BITS: usize = 8;
31pub const P256_BLOCK_SIZE: usize = 32;
32// from_const_bytes is little endian
33pub const CURVE_A: P256Coord = P256Coord::from_const_bytes(hex!(
34    "fcffffffffffffffffffffff00000000000000000000000001000000ffffffff"
35));
36pub const CURVE_B: P256Coord = P256Coord::from_const_bytes(hex!(
37    "4b60d2273e3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a"
38));
39
40openvm_ecc_sw_macros::sw_declare! {
41    P256Point { mod_type = P256Coord, a = CURVE_A, b = CURVE_B },
42}
43
44impl Field for P256Coord {
45    const ZERO: Self = <Self as IntMod>::ZERO;
46    const ONE: Self = <Self as IntMod>::ONE;
47
48    type SelfRef<'a> = &'a Self;
49
50    fn double_assign(&mut self) {
51        IntMod::double_assign(self);
52    }
53
54    fn square_assign(&mut self) {
55        IntMod::square_assign(self);
56    }
57}
58
59impl CyclicGroup for P256Point {
60    // The constants are taken from: https://neuromancer.sk/std/secg/secp256r1
61    const GENERATOR: Self = P256Point {
62        // from_const_bytes takes a little endian byte string
63        x: P256Coord::from_const_bytes(hex!(
64            "96c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b"
65        )),
66        y: P256Coord::from_const_bytes(hex!(
67            "f551bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f"
68        )),
69    };
70    const NEG_GENERATOR: Self = P256Point {
71        x: P256Coord::from_const_bytes(hex!(
72            "96c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b"
73        )),
74        y: P256Coord::from_const_bytes(hex!(
75            "0aae40c897bf493431a1ce94a9cc31d4e961f083b51418716580e5011cbd1cb0"
76        )),
77    };
78}
79
80impl IntrinsicCurve for p256::NistP256 {
81    type Scalar = P256Scalar;
82    type Point = P256Point;
83
84    fn msm(coeffs: &[Self::Scalar], bases: &[Self::Point]) -> Self::Point
85    where
86        for<'a> &'a Self::Point: Add<&'a Self::Point, Output = Self::Point>,
87    {
88        if coeffs.len() < 25 {
89            let table = CachedMulTable::<Self>::new_with_prime_order(bases, 4);
90            table.windowed_mul(coeffs)
91        } else {
92            crate::msm(coeffs, bases)
93        }
94    }
95}