1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use core::fmt; use core::ops::{Mul, Neg}; use ff::PrimeField; use subtle::{Choice, CtOption}; use crate::{prime::PrimeGroup, Curve, Group, GroupEncoding, GroupOps, GroupOpsOwned}; /// This trait represents an element of a cryptographic group with a large prime-order /// subgroup and a comparatively-small cofactor. pub trait CofactorGroup: Group + GroupEncoding + GroupOps<<Self as CofactorGroup>::Subgroup> + GroupOpsOwned<<Self as CofactorGroup>::Subgroup> { /// The large prime-order subgroup in which cryptographic operations are performed. /// If `Self` implements `PrimeGroup`, then `Self::Subgroup` may be `Self`. type Subgroup: PrimeGroup<Scalar = Self::Scalar> + Into<Self>; /// Maps `self` to the prime-order subgroup by multiplying this element by some /// `k`-multiple of the cofactor. /// /// The value `k` does not vary between inputs for a given implementation, but may /// vary between different implementations of `CofactorGroup` because some groups have /// more efficient methods of clearing the cofactor when `k` is allowed to be /// different than `1`. /// /// If `Self` implements [`PrimeGroup`], this returns `self`. fn clear_cofactor(&self) -> Self::Subgroup; /// Returns `self` if it is contained in the prime-order subgroup. /// /// If `Self` implements [`PrimeGroup`], this returns `Some(self)`. fn into_subgroup(self) -> CtOption<Self::Subgroup>; /// Determines if this element is of small order. /// /// Returns: /// - `true` if `self` is in the torsion subgroup. /// - `false` if `self` is not in the torsion subgroup. fn is_small_order(&self) -> Choice { self.clear_cofactor().is_identity() } /// Determines if this element is "torsion free", i.e., is contained in the /// prime-order subgroup. /// /// Returns: /// - `true` if `self` has zero torsion component and is in the prime-order subgroup. /// - `false` if `self` has non-zero torsion component and is not in the prime-order /// subgroup. fn is_torsion_free(&self) -> Choice { // Multiply self by the characteristic to eliminate any prime-order subgroup // component. let bits = Self::Scalar::char_le_bits(); let mut res = Self::identity(); for i in &bits { res = res.double(); if *i { res.add_assign(self) } } // If the result is the identity, there was zero torsion component! res.is_identity() } } /// Efficient representation of an elliptic curve point guaranteed to be /// in the correct prime order subgroup. pub trait CofactorCurve: Curve<AffineRepr = <Self as CofactorCurve>::Affine> + CofactorGroup { type Affine: CofactorCurveAffine<Curve = Self, Scalar = Self::Scalar> + Mul<Self::Scalar, Output = Self> + for<'r> Mul<Self::Scalar, Output = Self>; } /// Affine representation of an elliptic curve point guaranteed to be /// in the correct prime order subgroup. pub trait CofactorCurveAffine: GroupEncoding + Copy + Clone + Sized + Send + Sync + fmt::Debug + PartialEq + Eq + 'static + Neg<Output = Self> + Mul<<Self as CofactorCurveAffine>::Scalar, Output = <Self as CofactorCurveAffine>::Curve> + for<'r> Mul< <Self as CofactorCurveAffine>::Scalar, Output = <Self as CofactorCurveAffine>::Curve, > { type Scalar: PrimeField; type Curve: CofactorCurve<Affine = Self, Scalar = Self::Scalar>; /// Returns the additive identity. fn identity() -> Self; /// Returns a fixed generator of unknown exponent. fn generator() -> Self; /// Determines if this point represents the point at infinity; the /// additive identity. fn is_identity(&self) -> Choice; /// Converts this element to its curve representation. fn to_curve(&self) -> Self::Curve; }