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}