p256/
internal.rs

1use core::ops::{Add, Neg};
2
3use hex_literal::hex;
4use openvm_algebra_guest::IntMod;
5use openvm_algebra_moduli_macros::moduli_declare;
6use openvm_ecc_guest::{
7    weierstrass::{CachedMulTable, IntrinsicCurve, WeierstrassPoint},
8    CyclicGroup, Group,
9};
10use openvm_ecc_sw_macros::sw_declare;
11
12use crate::NistP256;
13
14// --- Define the OpenVM modular arithmetic and ecc types ---
15
16moduli_declare! {
17    P256Coord { modulus = "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff" },
18    P256Scalar { modulus = "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551" },
19}
20
21// from_const_bytes is little endian
22pub const CURVE_A: P256Coord = P256Coord::from_const_bytes(hex!(
23    "fcffffffffffffffffffffff00000000000000000000000001000000ffffffff"
24));
25pub const CURVE_B: P256Coord = P256Coord::from_const_bytes(hex!(
26    "4b60d2273e3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a"
27));
28
29sw_declare! {
30    P256Point { mod_type = P256Coord, a = CURVE_A, b = CURVE_B },
31}
32
33// --- Implement internal traits ---
34
35impl CyclicGroup for P256Point {
36    // The constants are taken from: https://neuromancer.sk/std/secg/secp256r1
37    const GENERATOR: Self = P256Point {
38        // from_const_bytes takes a little endian byte string
39        x: P256Coord::from_const_bytes(hex!(
40            "96c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b"
41        )),
42        y: P256Coord::from_const_bytes(hex!(
43            "f551bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f"
44        )),
45    };
46    const NEG_GENERATOR: Self = P256Point {
47        x: P256Coord::from_const_bytes(hex!(
48            "96c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce1f2d1176b"
49        )),
50        y: P256Coord::from_const_bytes(hex!(
51            "0aae40c897bf493431a1ce94a9cc31d4e961f083b51418716580e5011cbd1cb0"
52        )),
53    };
54}
55
56impl IntrinsicCurve for NistP256 {
57    type Scalar = P256Scalar;
58    type Point = P256Point;
59
60    fn msm(coeffs: &[Self::Scalar], bases: &[Self::Point]) -> Self::Point
61    where
62        for<'a> &'a Self::Point: Add<&'a Self::Point, Output = Self::Point>,
63    {
64        if coeffs.len() < 25 {
65            let table = CachedMulTable::<Self>::new_with_prime_order(bases, 4);
66            table.windowed_mul(coeffs)
67        } else {
68            openvm_ecc_guest::msm(coeffs, bases)
69        }
70    }
71}
72
73// --- Implement helpful methods mimicking the structs in p256 ---
74
75impl P256Point {
76    pub fn x_be_bytes(&self) -> [u8; 32] {
77        <Self as WeierstrassPoint>::x(self).to_be_bytes()
78    }
79
80    pub fn y_be_bytes(&self) -> [u8; 32] {
81        <Self as WeierstrassPoint>::y(self).to_be_bytes()
82    }
83}