mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Tweak multiexp to Zeroize points when invoked in constant time, not just scalars
This commit is contained in:
@@ -12,7 +12,7 @@ use crate::{multiexp, multiexp_vartime};
|
||||
// Flatten the contained statements to a single Vec.
|
||||
// Wrapped in Zeroizing in case any of the included statements contain private values.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn flat<Id: Copy + Zeroize, G: Group<Scalar: PrimeFieldBits + Zeroize> + Zeroize>(
|
||||
fn flat<Id: Copy + Zeroize, G: Zeroize + Group<Scalar: Zeroize + PrimeFieldBits>>(
|
||||
slice: &[(Id, Vec<(G::Scalar, G)>)],
|
||||
) -> Zeroizing<Vec<(G::Scalar, G)>> {
|
||||
Zeroizing::new(slice.iter().flat_map(|pairs| pairs.1.iter()).copied().collect::<Vec<_>>())
|
||||
@@ -21,11 +21,11 @@ fn flat<Id: Copy + Zeroize, G: Group<Scalar: PrimeFieldBits + Zeroize> + Zeroize
|
||||
/// A batch verifier intended to verify a series of statements are each equivalent to zero.
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[derive(Clone, Zeroize)]
|
||||
pub struct BatchVerifier<Id: Copy + Zeroize, G: Group<Scalar: PrimeFieldBits + Zeroize> + Zeroize>(
|
||||
pub struct BatchVerifier<Id: Copy + Zeroize, G: Zeroize + Group<Scalar: Zeroize + PrimeFieldBits>>(
|
||||
Zeroizing<Vec<(Id, Vec<(G::Scalar, G)>)>>,
|
||||
);
|
||||
|
||||
impl<Id: Copy + Zeroize, G: Group<Scalar: PrimeFieldBits + Zeroize> + Zeroize>
|
||||
impl<Id: Copy + Zeroize, G: Zeroize + Group<Scalar: Zeroize + PrimeFieldBits>>
|
||||
BatchVerifier<Id, G>
|
||||
{
|
||||
/// Create a new batch verifier, expected to verify the following amount of statements.
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
#[allow(unused_imports)]
|
||||
use std_shims::prelude::*;
|
||||
use std_shims::vec::Vec;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
@@ -175,7 +177,9 @@ fn algorithm(len: usize) -> Algorithm {
|
||||
|
||||
/// Performs a multiexponentiation, automatically selecting the optimal algorithm based on the
|
||||
/// amount of pairs.
|
||||
pub fn multiexp<G: Group<Scalar: PrimeFieldBits + Zeroize>>(pairs: &[(G::Scalar, G)]) -> G {
|
||||
pub fn multiexp<G: Zeroize + Group<Scalar: Zeroize + PrimeFieldBits>>(
|
||||
pairs: &[(G::Scalar, G)],
|
||||
) -> G {
|
||||
match algorithm(pairs.len()) {
|
||||
Algorithm::Null => Group::identity(),
|
||||
Algorithm::Single => pairs[0].1 * pairs[0].0,
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::prep_bits;
|
||||
|
||||
// Pippenger's algorithm for multiexponentiation, as published in the SIAM Journal on Computing
|
||||
// DOI: 10.1137/0209022
|
||||
pub(crate) fn pippenger<G: Group<Scalar: PrimeFieldBits>>(
|
||||
pub(crate) fn pippenger<G: Zeroize + Group<Scalar: PrimeFieldBits>>(
|
||||
pairs: &[(G::Scalar, G)],
|
||||
window: u8,
|
||||
) -> G {
|
||||
@@ -25,6 +25,7 @@ pub(crate) fn pippenger<G: Group<Scalar: PrimeFieldBits>>(
|
||||
for p in 0 .. bits.len() {
|
||||
buckets[usize::from(bits[p][n])] += pairs[p].1;
|
||||
}
|
||||
buckets.zeroize();
|
||||
|
||||
let mut intermediate_sum = G::identity();
|
||||
for b in (1 .. buckets.len()).rev() {
|
||||
|
||||
@@ -24,12 +24,12 @@ fn prep_tables<G: Group>(pairs: &[(G::Scalar, G)], window: u8) -> Vec<Vec<G>> {
|
||||
|
||||
// Straus's algorithm for multiexponentiation, as published in The American Mathematical Monthly
|
||||
// DOI: 10.2307/2310929
|
||||
pub(crate) fn straus<G: Group<Scalar: PrimeFieldBits + Zeroize>>(
|
||||
pub(crate) fn straus<G: Zeroize + Group<Scalar: PrimeFieldBits>>(
|
||||
pairs: &[(G::Scalar, G)],
|
||||
window: u8,
|
||||
) -> G {
|
||||
let mut groupings = prep_bits(pairs, window);
|
||||
let tables = prep_tables(pairs, window);
|
||||
let mut tables = prep_tables(pairs, window);
|
||||
|
||||
let mut res = G::identity();
|
||||
for b in (0 .. groupings[0].len()).rev() {
|
||||
@@ -45,6 +45,7 @@ pub(crate) fn straus<G: Group<Scalar: PrimeFieldBits + Zeroize>>(
|
||||
}
|
||||
|
||||
groupings.zeroize();
|
||||
tables.zeroize();
|
||||
res
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use group::Group;
|
||||
|
||||
use crate::BatchVerifier;
|
||||
|
||||
pub(crate) fn test_batch<G: Group<Scalar: PrimeFieldBits + Zeroize> + Zeroize>() {
|
||||
pub(crate) fn test_batch<G: Zeroize + Group<Scalar: Zeroize + PrimeFieldBits>>() {
|
||||
let valid = |batch: BatchVerifier<_, G>| {
|
||||
assert!(batch.verify());
|
||||
assert!(batch.verify_vartime());
|
||||
|
||||
@@ -18,7 +18,7 @@ mod batch;
|
||||
use batch::test_batch;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn benchmark_internal<G: Group<Scalar: PrimeFieldBits + Zeroize>>(straus_bool: bool) {
|
||||
fn benchmark_internal<G: Zeroize + Group<Scalar: Zeroize + PrimeFieldBits>>(straus_bool: bool) {
|
||||
let runs: usize = 20;
|
||||
|
||||
let mut start = 0;
|
||||
@@ -83,7 +83,7 @@ fn benchmark_internal<G: Group<Scalar: PrimeFieldBits + Zeroize>>(straus_bool: b
|
||||
}
|
||||
}
|
||||
|
||||
fn test_multiexp<G: Group<Scalar: PrimeFieldBits + Zeroize>>() {
|
||||
fn test_multiexp<G: Zeroize + Group<Scalar: Zeroize + PrimeFieldBits>>() {
|
||||
let test = |pairs: &[_], sum| {
|
||||
// These should automatically determine the best algorithm
|
||||
assert_eq!(multiexp(pairs), sum);
|
||||
|
||||
Reference in New Issue
Block a user