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;
}