elliptic_curve/
ops.rs

1//! Traits for arithmetic operations on elliptic curve field elements.
2
3pub use core::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
4
5use crypto_bigint::{ArrayEncoding, ByteArray, Integer};
6
7#[cfg(feature = "arithmetic")]
8use {group::Group, subtle::CtOption};
9
10#[cfg(feature = "digest")]
11use digest::FixedOutput;
12
13/// Perform an inversion on a field element (i.e. base field element or scalar)
14pub trait Invert {
15    /// Field element type
16    type Output;
17
18    /// Invert a field element.
19    fn invert(&self) -> Self::Output;
20}
21
22#[cfg(feature = "arithmetic")]
23impl<F: ff::Field> Invert for F {
24    type Output = CtOption<F>;
25
26    fn invert(&self) -> CtOption<F> {
27        ff::Field::invert(self)
28    }
29}
30
31/// Linear combination.
32///
33/// This trait enables crates to provide an optimized implementation of
34/// linear combinations (e.g. Shamir's Trick), or otherwise provides a default
35/// non-optimized implementation.
36// TODO(tarcieri): replace this with a trait from the `group` crate? (see zkcrypto/group#25)
37#[cfg(feature = "arithmetic")]
38#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
39pub trait LinearCombination: Group {
40    /// Calculates `x * k + y * l`.
41    fn lincomb(x: &Self, k: &Self::Scalar, y: &Self, l: &Self::Scalar) -> Self {
42        (*x * k) + (*y * l)
43    }
44}
45
46/// Modular reduction.
47pub trait Reduce<UInt: Integer + ArrayEncoding>: Sized {
48    /// Perform a modular reduction, returning a field element.
49    fn from_uint_reduced(n: UInt) -> Self;
50
51    /// Interpret the given byte array as a big endian integer and perform
52    /// a modular reduction.
53    fn from_be_bytes_reduced(bytes: ByteArray<UInt>) -> Self {
54        Self::from_uint_reduced(UInt::from_be_byte_array(bytes))
55    }
56
57    /// Interpret the given byte array as a little endian integer and perform a
58    /// modular reduction.
59    fn from_le_bytes_reduced(bytes: ByteArray<UInt>) -> Self {
60        Self::from_uint_reduced(UInt::from_le_byte_array(bytes))
61    }
62
63    /// Interpret a digest as a big endian integer and perform a modular
64    /// reduction.
65    #[cfg(feature = "digest")]
66    #[cfg_attr(docsrs, doc(cfg(feature = "digest")))]
67    fn from_be_digest_reduced<D>(digest: D) -> Self
68    where
69        D: FixedOutput<OutputSize = UInt::ByteSize>,
70    {
71        Self::from_be_bytes_reduced(digest.finalize_fixed())
72    }
73
74    /// Interpret a digest as a little endian integer and perform a modular
75    /// reduction.
76    #[cfg(feature = "digest")]
77    #[cfg_attr(docsrs, doc(cfg(feature = "digest")))]
78    fn from_le_digest_reduced<D>(digest: D) -> Self
79    where
80        D: FixedOutput<OutputSize = UInt::ByteSize>,
81    {
82        Self::from_le_bytes_reduced(digest.finalize_fixed())
83    }
84}
85
86/// Modular reduction to a non-zero output.
87///
88/// This trait is primarily intended for use by curve implementations such
89/// as the `k256` and `p256` crates.
90///
91/// End users should use the [`Reduce`] impl on
92/// [`NonZeroScalar`][`crate::NonZeroScalar`] instead.
93pub trait ReduceNonZero<UInt: Integer + ArrayEncoding>: Sized {
94    /// Perform a modular reduction, returning a field element.
95    fn from_uint_reduced_nonzero(n: UInt) -> Self;
96}