openzeppelin_crypto/curve/sw/
mod.rs

1//! This module contains definitions for the [Short Weierstrass model] of the
2//! curve.
3//!
4//! [Short Weierstrass model]: https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
5
6use num_traits::Zero;
7
8mod affine;
9pub use affine::*;
10
11mod projective;
12pub use projective::*;
13
14pub mod instance;
15
16use crate::{
17    bits::BitIteratorBE,
18    curve::AffineRepr,
19    field::{group::AdditiveGroup, prime::PrimeField},
20};
21
22/// Constants and convenience functions that collectively define the
23/// [Short Weierstrass model] of the curve.
24///
25/// In this model, the curve equation is `y² = x³ + a * x + b`, for constants
26/// `a` and `b`.
27///
28/// [Short Weierstrass model]: https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
29pub trait SWCurveConfig: super::CurveConfig {
30    /// Coefficient `a` of the curve equation.
31    const COEFF_A: Self::BaseField;
32    /// Coefficient `b` of the curve equation.
33    const COEFF_B: Self::BaseField;
34    /// Generator of the prime-order subgroup.
35    const GENERATOR: Affine<Self>;
36
37    /// Helper method for computing `elem * Self::COEFF_A`.
38    ///
39    /// The default implementation should be overridden only if
40    /// the product can be computed faster than standard field multiplication
41    /// (eg: via doubling if `COEFF_A == 2`, or if `COEFF_A.is_zero()`).
42    #[inline(always)]
43    fn mul_by_a(elem: Self::BaseField) -> Self::BaseField {
44        if Self::COEFF_A.is_zero() {
45            Self::BaseField::ZERO
46        } else {
47            elem * Self::COEFF_A
48        }
49    }
50
51    /// Helper method for computing `elem + Self::COEFF_B`.
52    ///
53    /// The default implementation should be overridden only if
54    /// the sum can be computed faster than standard field addition (eg: via
55    /// doubling).
56    #[inline(always)]
57    fn add_b(elem: Self::BaseField) -> Self::BaseField {
58        if Self::COEFF_B.is_zero() {
59            elem
60        } else {
61            elem + Self::COEFF_B
62        }
63    }
64
65    /// Check if the provided curve point is in the prime-order subgroup.
66    ///
67    /// The default implementation multiplies `item` by the order `r` of the
68    /// prime-order subgroup, and checks if the result is zero. If the
69    /// curve's cofactor is one, this check automatically returns true.
70    /// Implementors can choose to override this default impl
71    /// if the given curve has faster methods
72    /// for performing this check (for example, via leveraging curve
73    /// isomorphisms).
74    fn is_in_prime_order_subgroup(item: &Affine<Self>) -> bool {
75        Self::cofactor_is_one()
76            || Self::mul_affine(item, Self::ScalarField::characteristic())
77                .is_zero()
78    }
79
80    /// Performs cofactor clearing.
81    /// The default method is simply to multiply by the cofactor.
82    /// Some curves can implement a more efficient algorithm.
83    fn clear_cofactor(item: &Affine<Self>) -> Affine<Self> {
84        item.mul_by_cofactor()
85    }
86
87    /// Default implementation of group multiplication for projective
88    /// coordinates.
89    fn mul_projective(
90        base: &Projective<Self>,
91        scalar: impl BitIteratorBE,
92    ) -> Projective<Self> {
93        sw_double_and_add_projective(base, scalar)
94    }
95
96    /// Default implementation of group multiplication for affine
97    /// coordinates.
98    fn mul_affine(
99        base: &Affine<Self>,
100        scalar: impl BitIteratorBE,
101    ) -> Projective<Self> {
102        sw_double_and_add_affine(base, scalar)
103    }
104}
105
106/// Standard double-and-add method for multiplication by a scalar.
107#[inline(always)]
108pub fn sw_double_and_add_affine<P: SWCurveConfig>(
109    base: &Affine<P>,
110    scalar: impl BitIteratorBE,
111) -> Projective<P> {
112    let mut res = Projective::zero();
113    for b in scalar.bit_be_trimmed_iter() {
114        res.double_in_place();
115        if b {
116            res += base;
117        }
118    }
119
120    res
121}
122
123/// Standard double-and-add method for multiplication by a scalar.
124#[inline(always)]
125pub fn sw_double_and_add_projective<P: SWCurveConfig>(
126    base: &Projective<P>,
127    scalar: impl BitIteratorBE,
128) -> Projective<P> {
129    let mut res = Projective::zero();
130    for b in scalar.bit_be_trimmed_iter() {
131        res.double_in_place();
132        if b {
133            res += base;
134        }
135    }
136
137    res
138}