Skip to main content

rings_core/ecc/
group.rs

1//! Algebraic carriers and elliptic-curve adapters.
2//!
3//! The generic algebraic vocabulary lives in [`crate::algebra`]. This module
4//! connects those traits to concrete elliptic-curve libraries:
5//!
6//! - [`Point<C>`] is the curve element carrier and implements the additive
7//!   abelian-group and module traits.
8//! - [`Scalar<C>`] is the curve scalar carrier and implements the field traits.
9//! - [`CurveGroup`] is the adapter boundary for elliptic-curve libraries. A
10//!   marker type such as [`Secp256k1`] or [`Bls12381G1`] supplies native point
11//!   operations and scalar action.
12//! - [`CurveScalarField`] is the separate adapter boundary for scalar-field
13//!   operations and non-zero scalar sampling.
14//! - [`CyclicModule`] is the algebraic capability used by cryptographic
15//!   algorithms that require a distinguished generator and fresh non-zero
16//!   scalars.
17//!
18//! All operations are written in additive notation. For a scalar `x` and
19//! generator `g`, `xg` is represented by [`CyclicModule::generator_mul`].
20//!
21//! This split gives the rest of the cryptographic code one stable vocabulary:
22//! algorithms depend on algebraic carrier laws, not on a concrete crate such as
23//! `k256`, `p256`, `arkworks`, or `curve25519-dalek`. Adding a curve is
24//! therefore a matter of implementing the point and scalar adapter boundaries
25//! once; algorithms such as ElGamal do not need per-curve branches.
26
27use std::cell::RefCell;
28use std::convert::TryFrom;
29use std::ops::Add;
30use std::ops::Mul;
31use std::ops::Neg;
32use std::ops::Sub;
33
34use ark_bls12_381::Fr as Bls12381ScalarField;
35use ark_bls12_381::G1Projective;
36use ark_ec::PrimeGroup as _;
37use ark_ff::Field as _;
38use ark_ff::One as _;
39use ark_ff::Zero as _;
40use ark_std::UniformRand;
41#[cfg(feature = "curve-ristretto255")]
42use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
43#[cfg(feature = "curve-ristretto255")]
44use curve25519_dalek::ristretto::RistrettoPoint;
45#[cfg(feature = "curve-ristretto255")]
46use curve25519_dalek::scalar::Scalar as Ristretto255ScalarField;
47#[cfg(feature = "curve-ristretto255")]
48use curve25519_dalek::traits::Identity as _;
49use elliptic_curve::ff::Field as _;
50use k256::AffinePoint as K256AffinePoint;
51use k256::ProjectivePoint as K256ProjectivePoint;
52use k256::Scalar as K256Scalar;
53use p256::ProjectivePoint as Secp256r1ProjectivePoint;
54use p256::Scalar as Secp256r1ScalarField;
55use rand::RngCore;
56use rand::SeedableRng;
57use rand_hc::Hc128Rng;
58
59use crate::algebra::AbelianGroup;
60use crate::algebra::CommutativeRing;
61use crate::algebra::Field as AlgebraField;
62use crate::algebra::Module;
63use crate::algebra::One as AlgebraOne;
64use crate::algebra::Zero as AlgebraZero;
65use crate::ecc::PublicKey;
66use crate::ecc::SecretKey;
67use crate::error::Error;
68use crate::error::Result;
69
70/// Curve-specific point-group and scalar-action operations implemented by curve markers.
71///
72/// This trait is the adapter boundary between algebraic point carriers and
73/// concrete elliptic-curve libraries. For a marker `C`, the native `Point` type
74/// must represent elements of one finite abelian group, and `Scalar` must be the
75/// native scalar type used for the right module action. Scalar field operations
76/// live in [`CurveScalarField`], not here.
77///
78/// Implementors must preserve the following laws after accounting for native
79/// representation details such as projective coordinates:
80///
81/// - `identity` is a left and right identity for `add`.
82/// - `add` is associative and commutative over the represented group.
83/// - `neg(p)` is the additive inverse of `p`.
84/// - `eq` is an equivalence relation over group elements, not merely raw
85///   representation equality; equivalent projective representatives must
86///   compare equal.
87/// - `eq` is compatible with `add`, `neg`, `mul`, and `generator_mul`.
88/// - `generator_mul(s)` is equivalent to `mul(generator(), s)`.
89/// - scalar multiplication is a right module action:
90///   `mul(add(p, q), s) == add(mul(p, s), mul(q, s))`.
91pub trait CurveGroup {
92    /// Native point representation for this curve group.
93    type Point: Clone;
94    /// Native scalar representation for this curve group.
95    type Scalar: Clone;
96
97    /// Additive identity.
98    fn identity() -> Self::Point;
99
100    /// Distinguished generator.
101    fn generator() -> Self::Point;
102
103    /// Multiply the distinguished generator by a scalar.
104    fn generator_mul(scalar: &Self::Scalar) -> Self::Point {
105        let generator = Self::generator();
106        Self::mul(&generator, scalar)
107    }
108
109    /// Group addition.
110    fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point;
111
112    /// Group inverse.
113    fn neg(point: &Self::Point) -> Self::Point;
114
115    /// Scalar multiplication.
116    fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point;
117
118    /// Element equality.
119    fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool;
120}
121
122/// Curve-specific scalar-field operations implemented by curve markers.
123///
124/// This trait is intentionally separate from [`CurveGroup`]. A curve point
125/// group and its scalar field are related by the module action, but they are
126/// different carriers with different operations and different law obligations.
127///
128/// Implementors must preserve these laws:
129///
130/// - scalars form a finite [`Field`](crate::algebra::Field);
131/// - `scalar_eq` is total equality over canonical scalar values;
132/// - `random_scalar_with_rng` returns a non-zero scalar.
133pub trait CurveScalarField: CurveGroup {
134    /// Scalar additive identity.
135    fn scalar_zero() -> Self::Scalar;
136
137    /// Scalar multiplicative identity.
138    fn scalar_one() -> Self::Scalar;
139
140    /// Return whether the scalar is the additive identity.
141    fn scalar_is_zero(scalar: &Self::Scalar) -> bool;
142
143    /// Scalar addition.
144    fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
145
146    /// Scalar subtraction.
147    fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
148
149    /// Scalar additive inverse.
150    fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar;
151
152    /// Scalar multiplication.
153    fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar;
154
155    /// Scalar multiplicative inverse.
156    fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar>;
157
158    /// Scalar equality.
159    fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool;
160
161    /// Generate a fresh non-zero random scalar from an explicit RNG.
162    fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar;
163
164    /// Generate a fresh non-zero random scalar from the default thread-local RNG.
165    fn random_scalar() -> Self::Scalar {
166        with_group_rng(|rng| Self::random_scalar_with_rng(rng))
167    }
168}
169
170/// Algebraic carrier with a distinguished generator and non-zero scalar sampler.
171///
172/// This is not a replacement group hierarchy; it is the extra capability needed
173/// by cryptographic algorithms such as ElGamal after the carrier already
174/// implements [`AbelianGroup`] and [`Module`]. The implementation obligation is
175/// that `generator_mul(s)` equals `generator() * s` and that sampled scalars are
176/// non-zero field elements.
177///
178/// `Module<Self::Scalar>` stays as an explicit consumer bound instead of a
179/// supertrait here. `CyclicModule` introduces the associated scalar type, while
180/// [`Module`] proves the right scalar action for arbitrary elements; consumers
181/// that multiply elements by scalars should request both
182/// `CyclicModule` and `Module<Element::Scalar>`. This keeps the generator and
183/// sampling capability separate from the module-action proof while still
184/// requiring `generator_mul(s)` to be observationally equal to `generator() * s`.
185///
186/// Non-zero scalar sampling also appears in [`CurveScalarField`] intentionally.
187/// Curve adapters provide the native scalar-field sampler; `CyclicModule`
188/// exposes the same cryptographic capability through the element carrier so
189/// algorithms do not need to know the curve marker type.
190pub trait CyclicModule: AbelianGroup + Sized {
191    /// Scalar field for the module action.
192    type Scalar: AlgebraField;
193
194    /// Distinguished generator for the cyclic subgroup used by the algorithm.
195    fn generator() -> Self;
196
197    /// Multiply the distinguished generator by a scalar.
198    fn generator_mul(scalar: &Self::Scalar) -> Self;
199
200    /// Generate a fresh non-zero random scalar from an explicit RNG.
201    fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar;
202
203    /// Generate a fresh non-zero random scalar from the default thread-local RNG.
204    fn random_scalar() -> Self::Scalar {
205        with_group_rng(|rng| Self::random_scalar_with_rng(rng))
206    }
207}
208
209/// Generic group element for curve marker `C`.
210#[derive(Debug)]
211pub struct Point<C: CurveGroup> {
212    inner: C::Point,
213}
214
215/// Generic scalar for curve marker `C`.
216#[derive(Debug)]
217pub struct Scalar<C: CurveGroup> {
218    inner: C::Scalar,
219}
220
221/// secp256k1 curve marker.
222#[derive(Debug)]
223pub struct Secp256k1;
224
225/// secp256r1/P-256 curve marker.
226#[derive(Debug)]
227pub struct Secp256r1;
228
229/// BLS12-381 G1 curve marker.
230#[derive(Debug)]
231pub struct Bls12381G1;
232
233/// Ristretto255 group marker.
234#[cfg(feature = "curve-ristretto255")]
235#[derive(Debug)]
236pub struct Ristretto255;
237
238thread_local! {
239    static GROUP_RNG: RefCell<Hc128Rng> = RefCell::new(Hc128Rng::from_entropy());
240}
241
242impl<C: CurveGroup> Point<C> {
243    /// Build a group element from the curve-native point type.
244    pub fn new(inner: C::Point) -> Self {
245        Self { inner }
246    }
247
248    /// Borrow the curve-native point type.
249    pub fn as_inner(&self) -> &C::Point {
250        &self.inner
251    }
252
253    /// Unwrap into the curve-native point type.
254    pub fn into_inner(self) -> C::Point {
255        self.inner
256    }
257}
258
259impl<C: CurveGroup> Scalar<C> {
260    /// Build a scalar from the curve-native scalar type.
261    pub fn new(inner: C::Scalar) -> Self {
262        Self { inner }
263    }
264
265    /// Borrow the curve-native scalar type.
266    pub fn as_inner(&self) -> &C::Scalar {
267        &self.inner
268    }
269
270    /// Unwrap into the curve-native scalar type.
271    pub fn into_inner(self) -> C::Scalar {
272        self.inner
273    }
274}
275
276impl<C: CurveGroup> Clone for Point<C> {
277    fn clone(&self) -> Self {
278        Self::new(self.inner.clone())
279    }
280}
281
282impl<C> Copy for Point<C>
283where
284    C: CurveGroup,
285    C::Point: Copy,
286{
287}
288
289impl<C: CurveGroup> Clone for Scalar<C> {
290    fn clone(&self) -> Self {
291        Self::new(self.inner.clone())
292    }
293}
294
295impl<C> Copy for Scalar<C>
296where
297    C: CurveGroup,
298    C::Scalar: Copy,
299{
300}
301
302impl<C: CurveGroup> Add for Point<C> {
303    type Output = Self;
304
305    fn add(self, rhs: Self) -> Self::Output {
306        Self::new(C::add(&self.inner, &rhs.inner))
307    }
308}
309
310impl<C: CurveGroup> Neg for Point<C> {
311    type Output = Self;
312
313    fn neg(self) -> Self::Output {
314        Self::new(C::neg(&self.inner))
315    }
316}
317
318impl<C: CurveGroup> Sub for Point<C> {
319    type Output = Self;
320
321    fn sub(self, rhs: Self) -> Self::Output {
322        self + (-rhs)
323    }
324}
325
326impl<C: CurveGroup> Mul<Scalar<C>> for Point<C> {
327    type Output = Self;
328
329    fn mul(self, rhs: Scalar<C>) -> Self::Output {
330        Self::new(C::mul(&self.inner, &rhs.inner))
331    }
332}
333
334impl<C: CurveGroup> PartialEq for Point<C> {
335    fn eq(&self, other: &Self) -> bool {
336        C::eq(&self.inner, &other.inner)
337    }
338}
339
340impl<C: CurveGroup> Eq for Point<C> {}
341
342impl<C: CurveGroup> AlgebraZero for Point<C> {
343    fn zero() -> Self {
344        Self::new(C::identity())
345    }
346
347    fn is_zero(&self) -> bool {
348        C::eq(&self.inner, &C::identity())
349    }
350}
351
352impl<C: CurveGroup> AbelianGroup for Point<C> {}
353
354impl<C: CurveScalarField> Module<Scalar<C>> for Point<C> {}
355
356impl<C: CurveScalarField> CyclicModule for Point<C> {
357    type Scalar = Scalar<C>;
358
359    fn generator() -> Self {
360        Self::new(C::generator())
361    }
362
363    fn generator_mul(scalar: &Self::Scalar) -> Self {
364        Self::new(C::generator_mul(&scalar.inner))
365    }
366
367    fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
368        Scalar::new(C::random_scalar_with_rng(rng))
369    }
370}
371
372impl<C: CurveScalarField> Add for Scalar<C> {
373    type Output = Self;
374
375    fn add(self, rhs: Self) -> Self::Output {
376        Self::new(C::scalar_add(&self.inner, &rhs.inner))
377    }
378}
379
380impl<C: CurveScalarField> Sub for Scalar<C> {
381    type Output = Self;
382
383    fn sub(self, rhs: Self) -> Self::Output {
384        Self::new(C::scalar_sub(&self.inner, &rhs.inner))
385    }
386}
387
388impl<C: CurveScalarField> Neg for Scalar<C> {
389    type Output = Self;
390
391    fn neg(self) -> Self::Output {
392        Self::new(C::scalar_neg(&self.inner))
393    }
394}
395
396impl<C: CurveScalarField> Mul for Scalar<C> {
397    type Output = Self;
398
399    fn mul(self, rhs: Self) -> Self::Output {
400        Self::new(C::scalar_mul(&self.inner, &rhs.inner))
401    }
402}
403
404impl<C: CurveScalarField> PartialEq for Scalar<C> {
405    fn eq(&self, other: &Self) -> bool {
406        C::scalar_eq(&self.inner, &other.inner)
407    }
408}
409
410impl<C: CurveScalarField> Eq for Scalar<C> {}
411
412impl<C: CurveScalarField> AlgebraZero for Scalar<C> {
413    fn zero() -> Self {
414        Self::new(C::scalar_zero())
415    }
416
417    fn is_zero(&self) -> bool {
418        C::scalar_is_zero(&self.inner)
419    }
420}
421
422impl<C: CurveScalarField> AlgebraOne for Scalar<C> {
423    fn one() -> Self {
424        Self::new(C::scalar_one())
425    }
426}
427
428impl<C: CurveScalarField> AbelianGroup for Scalar<C> {}
429
430impl<C: CurveScalarField> CommutativeRing for Scalar<C> {}
431
432impl<C: CurveScalarField> AlgebraField for Scalar<C> {
433    fn try_inverse(&self) -> Option<Self> {
434        C::scalar_inverse(&self.inner).map(Self::new)
435    }
436}
437
438// The simple curve adapters below all have the same shape: the native library
439// already exposes identity, generator, addition, negation, scalar
440// multiplication, equality, and point conversion. Keeping that pattern in one
441// macro makes each supported curve a short declaration while preserving the
442// explicit algebraic operations at the trait boundary.
443macro_rules! impl_curve_group_adapter {
444    (
445        $curve:ty {
446            point: $point:ty,
447            scalar: $scalar:ty,
448            identity: $identity:expr,
449            generator: $generator:expr,
450            random_scalar: |$rng:ident| $random_scalar:block,
451            add: $add:expr,
452            neg: $neg:expr,
453            mul: $mul:expr,
454            eq: $eq:expr,
455            scalar_zero: $scalar_zero:expr,
456            scalar_one: $scalar_one:expr,
457            scalar_is_zero: $scalar_is_zero:expr,
458            scalar_add: $scalar_add:expr,
459            scalar_sub: $scalar_sub:expr,
460            scalar_neg: $scalar_neg:expr,
461            scalar_mul: $scalar_mul:expr,
462            scalar_inverse: $scalar_inverse:expr,
463            scalar_eq: $scalar_eq:expr $(,)?
464        }
465    ) => {
466        impl CurveGroup for $curve {
467            type Point = $point;
468            type Scalar = $scalar;
469
470            fn identity() -> Self::Point {
471                $identity
472            }
473
474            fn generator() -> Self::Point {
475                $generator
476            }
477
478            fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point {
479                ($add)(lhs, rhs)
480            }
481
482            fn neg(point: &Self::Point) -> Self::Point {
483                ($neg)(point)
484            }
485
486            fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point {
487                ($mul)(point, scalar)
488            }
489
490            fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool {
491                ($eq)(lhs, rhs)
492            }
493        }
494
495        impl CurveScalarField for $curve {
496            fn scalar_zero() -> Self::Scalar {
497                $scalar_zero
498            }
499
500            fn scalar_one() -> Self::Scalar {
501                $scalar_one
502            }
503
504            fn scalar_is_zero(scalar: &Self::Scalar) -> bool {
505                ($scalar_is_zero)(scalar)
506            }
507
508            fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
509                ($scalar_add)(lhs, rhs)
510            }
511
512            fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
513                ($scalar_sub)(lhs, rhs)
514            }
515
516            fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar {
517                ($scalar_neg)(scalar)
518            }
519
520            fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
521                ($scalar_mul)(lhs, rhs)
522            }
523
524            fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar> {
525                ($scalar_inverse)(scalar)
526            }
527
528            fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool {
529                ($scalar_eq)(lhs, rhs)
530            }
531
532            fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
533                let $rng = rng;
534                $random_scalar
535            }
536        }
537
538        impl From<$point> for Point<$curve> {
539            fn from(point: $point) -> Self {
540                Self::new(point)
541            }
542        }
543
544        impl From<Point<$curve>> for $point {
545            fn from(point: Point<$curve>) -> Self {
546                point.inner
547            }
548        }
549    };
550}
551
552impl CurveGroup for Secp256k1 {
553    type Point = K256ProjectivePoint;
554    type Scalar = K256Scalar;
555
556    fn identity() -> Self::Point {
557        K256ProjectivePoint::IDENTITY
558    }
559
560    fn generator() -> Self::Point {
561        K256ProjectivePoint::GENERATOR
562    }
563
564    fn add(lhs: &Self::Point, rhs: &Self::Point) -> Self::Point {
565        *lhs + *rhs
566    }
567
568    fn neg(point: &Self::Point) -> Self::Point {
569        -*point
570    }
571
572    fn mul(point: &Self::Point, scalar: &Self::Scalar) -> Self::Point {
573        *point * *scalar
574    }
575
576    fn eq(lhs: &Self::Point, rhs: &Self::Point) -> bool {
577        lhs == rhs
578    }
579}
580
581impl CurveScalarField for Secp256k1 {
582    fn scalar_zero() -> Self::Scalar {
583        K256Scalar::ZERO
584    }
585
586    fn scalar_one() -> Self::Scalar {
587        K256Scalar::ONE
588    }
589
590    fn scalar_is_zero(scalar: &Self::Scalar) -> bool {
591        bool::from(scalar.is_zero())
592    }
593
594    fn scalar_add(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
595        *lhs + *rhs
596    }
597
598    fn scalar_sub(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
599        *lhs - *rhs
600    }
601
602    fn scalar_neg(scalar: &Self::Scalar) -> Self::Scalar {
603        -*scalar
604    }
605
606    fn scalar_mul(lhs: &Self::Scalar, rhs: &Self::Scalar) -> Self::Scalar {
607        *lhs * *rhs
608    }
609
610    fn scalar_inverse(scalar: &Self::Scalar) -> Option<Self::Scalar> {
611        scalar.invert().into_option()
612    }
613
614    fn scalar_eq(lhs: &Self::Scalar, rhs: &Self::Scalar) -> bool {
615        lhs == rhs
616    }
617
618    fn random_scalar_with_rng(rng: &mut impl RngCore) -> Self::Scalar {
619        loop {
620            let scalar = K256Scalar::generate_vartime(rng);
621            if !bool::from(scalar.is_zero()) {
622                break scalar;
623            }
624        }
625    }
626}
627
628impl_curve_group_adapter! {
629    Secp256r1 {
630        point: Secp256r1ProjectivePoint,
631        scalar: Secp256r1ScalarField,
632        identity: Secp256r1ProjectivePoint::IDENTITY,
633        generator: Secp256r1ProjectivePoint::GENERATOR,
634        random_scalar: |rng| {
635            loop {
636                let scalar = Secp256r1ScalarField::random(&mut *rng);
637                if !bool::from(scalar.is_zero()) {
638                    break scalar;
639                }
640            }
641        },
642        add: |lhs: &Secp256r1ProjectivePoint, rhs: &Secp256r1ProjectivePoint| *lhs + *rhs,
643        neg: |point: &Secp256r1ProjectivePoint| -*point,
644        mul: |point: &Secp256r1ProjectivePoint, scalar: &Secp256r1ScalarField| *point * *scalar,
645        eq: |lhs: &Secp256r1ProjectivePoint, rhs: &Secp256r1ProjectivePoint| lhs == rhs,
646        scalar_zero: Secp256r1ScalarField::ZERO,
647        scalar_one: Secp256r1ScalarField::ONE,
648        scalar_is_zero: |scalar: &Secp256r1ScalarField| bool::from(scalar.is_zero()),
649        scalar_add: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs + *rhs,
650        scalar_sub: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs - *rhs,
651        scalar_neg: |scalar: &Secp256r1ScalarField| -*scalar,
652        scalar_mul: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| *lhs * *rhs,
653        scalar_inverse: |scalar: &Secp256r1ScalarField| scalar.invert().into_option(),
654        scalar_eq: |lhs: &Secp256r1ScalarField, rhs: &Secp256r1ScalarField| lhs == rhs,
655    }
656}
657
658impl_curve_group_adapter! {
659    Bls12381G1 {
660        point: G1Projective,
661        scalar: Bls12381ScalarField,
662        identity: G1Projective::zero(),
663        generator: G1Projective::generator(),
664        random_scalar: |rng| {
665            loop {
666                let scalar = Bls12381ScalarField::rand(&mut *rng);
667                if !scalar.is_zero() {
668                    break scalar;
669                }
670            }
671        },
672        add: |lhs: &G1Projective, rhs: &G1Projective| *lhs + *rhs,
673        neg: |point: &G1Projective| -*point,
674        mul: |point: &G1Projective, scalar: &Bls12381ScalarField| *point * *scalar,
675        eq: |lhs: &G1Projective, rhs: &G1Projective| lhs == rhs,
676        scalar_zero: Bls12381ScalarField::zero(),
677        scalar_one: Bls12381ScalarField::one(),
678        scalar_is_zero: |scalar: &Bls12381ScalarField| scalar.is_zero(),
679        scalar_add: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs + *rhs,
680        scalar_sub: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs - *rhs,
681        scalar_neg: |scalar: &Bls12381ScalarField| -*scalar,
682        scalar_mul: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| *lhs * *rhs,
683        scalar_inverse: |scalar: &Bls12381ScalarField| scalar.inverse(),
684        scalar_eq: |lhs: &Bls12381ScalarField, rhs: &Bls12381ScalarField| lhs == rhs,
685    }
686}
687
688#[cfg(feature = "curve-ristretto255")]
689impl_curve_group_adapter! {
690    Ristretto255 {
691        point: RistrettoPoint,
692        scalar: Ristretto255ScalarField,
693        identity: RistrettoPoint::identity(),
694        generator: RISTRETTO_BASEPOINT_POINT,
695        random_scalar: |rng| {
696            loop {
697                let mut bytes = [0u8; 64];
698                rng.fill_bytes(&mut bytes);
699                let scalar = Ristretto255ScalarField::from_bytes_mod_order_wide(&bytes);
700                if scalar != Ristretto255ScalarField::ZERO {
701                    break scalar;
702                }
703            }
704        },
705        add: |lhs: &RistrettoPoint, rhs: &RistrettoPoint| lhs + rhs,
706        neg: |point: &RistrettoPoint| -point,
707        mul: |point: &RistrettoPoint, scalar: &Ristretto255ScalarField| point * scalar,
708        eq: |lhs: &RistrettoPoint, rhs: &RistrettoPoint| lhs == rhs,
709        scalar_zero: Ristretto255ScalarField::ZERO,
710        scalar_one: Ristretto255ScalarField::ONE,
711        scalar_is_zero: |scalar: &Ristretto255ScalarField| *scalar == Ristretto255ScalarField::ZERO,
712        scalar_add: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs + *rhs,
713        scalar_sub: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs - *rhs,
714        scalar_neg: |scalar: &Ristretto255ScalarField| -*scalar,
715        scalar_mul: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| *lhs * *rhs,
716        scalar_inverse: |scalar: &Ristretto255ScalarField| {
717            if *scalar == Ristretto255ScalarField::ZERO {
718                None
719            } else {
720                Some(scalar.invert())
721            }
722        },
723        scalar_eq: |lhs: &Ristretto255ScalarField, rhs: &Ristretto255ScalarField| lhs == rhs,
724    }
725}
726
727impl From<SecretKey> for Scalar<Secp256k1> {
728    fn from(secret_key: SecretKey) -> Self {
729        Self::new(secret_key.secp256k1_scalar())
730    }
731}
732
733impl From<K256AffinePoint> for Point<Secp256k1> {
734    fn from(point: K256AffinePoint) -> Self {
735        Self::new(K256ProjectivePoint::from(point))
736    }
737}
738
739impl From<Point<Secp256k1>> for K256AffinePoint {
740    fn from(point: Point<Secp256k1>) -> Self {
741        point.inner.to_affine()
742    }
743}
744
745impl TryFrom<PublicKey<33>> for Point<Secp256k1> {
746    type Error = Error;
747
748    fn try_from(public_key: PublicKey<33>) -> Result<Self> {
749        let point: K256AffinePoint = public_key.try_into()?;
750        Ok(point.into())
751    }
752}
753
754impl TryFrom<Point<Secp256k1>> for PublicKey<33> {
755    type Error = Error;
756
757    fn try_from(point: Point<Secp256k1>) -> Result<Self> {
758        if point.inner == K256ProjectivePoint::IDENTITY {
759            return Err(Error::InvalidPublicKey);
760        }
761        K256AffinePoint::from(point).try_into()
762    }
763}
764
765fn with_group_rng<R>(f: impl FnOnce(&mut Hc128Rng) -> R) -> R {
766    GROUP_RNG.with(|rng| {
767        let mut rng = rng.borrow_mut();
768        f(&mut rng)
769    })
770}
771
772#[cfg(test)]
773mod tests {
774    use super::*;
775    use crate::algebra::assert_field_laws;
776    use crate::algebra::assert_module_action_laws;
777    use crate::algebra::One;
778    use crate::algebra::Zero;
779
780    fn cyclic_module_laws<Element>()
781    where
782        Element: CyclicModule + Module<Element::Scalar> + Clone + Eq + std::fmt::Debug,
783        Element::Scalar: Clone + Eq + std::fmt::Debug,
784    {
785        let scalar_a = Element::random_scalar();
786        let scalar_b = Element::random_scalar();
787        let scalar_c = Element::random_scalar();
788        let a = Element::generator() * scalar_a.clone();
789        let b = Element::generator() * scalar_b;
790        let c = Element::generator() * scalar_c;
791
792        assert_eq!(a.clone() + Element::zero(), a);
793        assert_eq!(Element::zero() + a.clone(), a);
794        assert_eq!(a.clone() + -a.clone(), Element::zero());
795        assert_eq!((a.clone() + b.clone()) + c.clone(), a + (b + c));
796        assert_eq!(
797            Element::generator_mul(&scalar_a),
798            Element::generator() * scalar_a
799        );
800    }
801
802    fn algebra_laws<C>()
803    where
804        C: CurveScalarField,
805        Point<C>: Eq + std::fmt::Debug,
806        Scalar<C>: Eq + std::fmt::Debug,
807    {
808        let scalar_a = Scalar::<C>::new(C::random_scalar());
809        let scalar_b = Scalar::<C>::new(C::random_scalar());
810        let scalar_c = Scalar::<C>::new(C::random_scalar());
811        let scalars = vec![
812            Scalar::<C>::zero(),
813            Scalar::<C>::one(),
814            scalar_a.clone(),
815            scalar_b.clone(),
816            scalar_c.clone(),
817        ];
818
819        let generator = Point::<C>::new(C::generator());
820        let points = vec![
821            Point::<C>::zero(),
822            generator.clone(),
823            generator.clone() * scalar_a,
824            generator.clone() * scalar_b,
825            generator * scalar_c,
826        ];
827
828        assert_field_laws(&scalars);
829        assert_module_action_laws(&scalars, &points);
830    }
831
832    #[test]
833    fn test_supported_curve_groups_satisfy_basic_laws() {
834        cyclic_module_laws::<Point<Secp256k1>>();
835        cyclic_module_laws::<Point<Secp256r1>>();
836        cyclic_module_laws::<Point<Bls12381G1>>();
837        #[cfg(feature = "curve-ristretto255")]
838        cyclic_module_laws::<Point<Ristretto255>>();
839    }
840
841    #[test]
842    fn test_supported_curve_groups_satisfy_algebra_laws() {
843        algebra_laws::<Secp256k1>();
844        algebra_laws::<Secp256r1>();
845        algebra_laws::<Bls12381G1>();
846        #[cfg(feature = "curve-ristretto255")]
847        algebra_laws::<Ristretto255>();
848    }
849}