Function curve25519_dalek::ristretto::multiscalar_mul [] [src]

pub fn multiscalar_mul<I, J>(scalars: I, points: J) -> RistrettoPoint where
    I: IntoIterator,
    I::Item: Borrow<Scalar>,
    J: IntoIterator,
    J::Item: Borrow<RistrettoPoint>, 

Given an iterator of (possibly secret) scalars and an iterator of (possibly secret) points, compute $$ Q = c_1 P_1 + \cdots + c_n P_n. $$

This function has the same behaviour as vartime::multiscalar_mul but is constant-time.

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<RistrettoPoint>), to allow iterators returning either Scalars or &Scalars.

use curve25519_dalek::{constants, ristretto};
use curve25519_dalek::scalar::Scalar;

// Some scalars
let a = Scalar::from_u64(87329482);
let b = Scalar::from_u64(37264829);
let c = Scalar::from_u64(98098098);

// 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 = ristretto::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 = ristretto::multiscalar_mul(minus_abc, &[P,Q,R]);
// Note: minus_abc.into_iter(): Iterator<Item=Scalar>

assert_eq!(A1.compress(), (-A2).compress());