betrusted-curve25519-dalek-.../src/traits.rs
Henry de Valence 1e74cb3e56 Replace Scalar::from_u64 with From impls
Unfortunately, Rust selects `i32` as the type for an integer literal
when the literal has no other type constraints.  This means that someone
cannot write `Scalar::from(1)`, as Rust will choose `i32` as the type for
`1`, and we don't `impl From<i32> for Scalar`.

We could implement `From` conversions for signed integers, but since
`Scalar` operations should be constant-time by default, this would
require us to extract the sign bit of the integer and use it to
conditionally select between the positive and negative of Scalar
constructed from the value bits.  This is more expensive than the
unsigned operation, and I don't think it's what anyone really wants.

Making API consumers specify that their literals are unsigned is
slightly annoying, but better than the above alternative.

It would also be nice to change `Scalar::from_hash` to be
`impl<D: Digest<OutputSize = U64>> From<D> for Scalar`,
but this isn't currently allowed by Rust (since that `impl` "could"
conflict with the `impl From<u8>` if someone decided that `u8` should
`impl Digest`).
2018-07-19 08:39:09 -07:00

172 lines
5.6 KiB
Rust

// -*- mode: rust; -*-
//
// This file is part of curve25519-dalek.
// Copyright (c) 2016-2018 Isis Lovecruft, Henry de Valence
// See LICENSE for licensing information.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
// - Henry de Valence <hdevalence@hdevalence.ca>
//! Module for common traits.
use core::borrow::Borrow;
use subtle;
use scalar::Scalar;
// ------------------------------------------------------------------------
// Public Traits
// ------------------------------------------------------------------------
/// Trait for getting the identity element of a point type.
pub trait Identity {
/// Returns the identity element of the curve.
/// Can be used as a constructor.
fn identity() -> Self;
}
/// Trait for testing if a curve point is equivalent to the identity point.
pub trait IsIdentity {
/// Return true if this element is the identity element of the curve.
fn is_identity(&self) -> bool;
}
/// Implement generic identity equality testing for a point representations
/// which have constant-time equality testing and a defined identity
/// constructor.
impl<T> IsIdentity for T
where
T: subtle::ConstantTimeEq + Identity,
{
fn is_identity(&self) -> bool {
self.ct_eq(&T::identity()).unwrap_u8() == 1u8
}
}
/// A trait for constant-time multiscalar multiplication without precomputation.
pub trait MultiscalarMul {
/// The type of point being multiplied, e.g., `RistrettoPoint`.
type Point;
/// Given an iterator of (possibly secret) scalars and an iterator of
/// public points, compute
/// $$
/// Q = c\_1 P\_1 + \cdots + c\_n P\_n.
/// $$
///
/// It is an error to call this function with two iterators of different lengths.
///
/// # Examples
///
/// The trait bound aims for maximum flexibility: the inputs must be
/// convertable to iterators (`I: IntoIter`), and the iterator's items
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
/// iterators returning either `Scalar`s or `&Scalar`s.
///
/// ```
/// use curve25519_dalek::constants;
/// use curve25519_dalek::traits::MultiscalarMul;
/// use curve25519_dalek::ristretto::RistrettoPoint;
/// use curve25519_dalek::scalar::Scalar;
///
/// // Some scalars
/// let a = Scalar::from(87329482u64);
/// let b = Scalar::from(37264829u64);
/// let c = Scalar::from(98098098u64);
///
/// // Some points
/// let P = constants::RISTRETTO_BASEPOINT_POINT;
/// let Q = P + P;
/// let R = P + Q;
///
/// // A1 = a*P + b*Q + c*R
/// let abc = [a,b,c];
/// let A1 = RistrettoPoint::multiscalar_mul(&abc, &[P,Q,R]);
/// // Note: (&abc).into_iter(): Iterator<Item=&Scalar>
///
/// // A2 = (-a)*P + (-b)*Q + (-c)*R
/// let minus_abc = abc.iter().map(|x| -x);
/// let A2 = RistrettoPoint::multiscalar_mul(minus_abc, &[P,Q,R]);
/// // Note: minus_abc.into_iter(): Iterator<Item=Scalar>
///
/// assert_eq!(A1.compress(), (-A2).compress());
/// ```
fn multiscalar_mul<I, J>(scalars: I, points: J) -> Self::Point
where
I: IntoIterator,
I::Item: Borrow<Scalar>,
J: IntoIterator,
J::Item: Borrow<Self::Point>;
}
/// A trait for variable-time multiscalar multiplication without precomputation.
pub trait VartimeMultiscalarMul {
/// The type of point being multiplied, e.g., `RistrettoPoint`.
type Point;
/// Given an iterator of (possibly secret) scalars and an iterator of
/// public points, compute
/// $$
/// Q = c\_1 P\_1 + \cdots + c\_n P\_n.
/// $$
///
/// It is an error to call this function with two iterators of different lengths.
///
/// # Examples
///
/// The trait bound aims for maximum flexibility: the inputs must be
/// convertable to iterators (`I: IntoIter`), and the iterator's items
/// must be `Borrow<Scalar>` (or `Borrow<Point>`), to allow
/// iterators returning either `Scalar`s or `&Scalar`s.
///
/// ```
/// use curve25519_dalek::constants;
/// use curve25519_dalek::traits::MultiscalarMul;
/// use curve25519_dalek::ristretto::RistrettoPoint;
/// use curve25519_dalek::scalar::Scalar;
///
/// // Some scalars
/// let a = Scalar::from(87329482u64);
/// let b = Scalar::from(37264829u64);
/// let c = Scalar::from(98098098u64);
///
/// // Some points
/// let P = constants::RISTRETTO_BASEPOINT_POINT;
/// let Q = P + P;
/// let R = P + Q;
///
/// // A1 = a*P + b*Q + c*R
/// let abc = [a,b,c];
/// let A1 = RistrettoPoint::multiscalar_mul(&abc, &[P,Q,R]);
/// // Note: (&abc).into_iter(): Iterator<Item=&Scalar>
///
/// // A2 = (-a)*P + (-b)*Q + (-c)*R
/// let minus_abc = abc.iter().map(|x| -x);
/// let A2 = RistrettoPoint::multiscalar_mul(minus_abc, &[P,Q,R]);
/// // Note: minus_abc.into_iter(): Iterator<Item=Scalar>
///
/// assert_eq!(A1.compress(), (-A2).compress());
/// ```
fn vartime_multiscalar_mul<I, J>(scalars: I, points: J) -> Self::Point
where
I: IntoIterator,
I::Item: Borrow<Scalar>,
J: IntoIterator,
J::Item: Borrow<Self::Point>;
}
// ------------------------------------------------------------------------
// Private Traits
// ------------------------------------------------------------------------
/// Trait for checking whether a point is on the curve.
///
/// This trait is only for debugging/testing, since it should be
/// impossible for a `curve25519-dalek` user to construct an invalid
/// point.
pub(crate) trait ValidityCheck {
/// Checks whether the point is on the curve. Not CT.
fn is_valid(&self) -> bool;
}