Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ serde = { version = "1", default-features = false, features = ["alloc"] }
serde_derive = { version = "1", default-features = false }
thiserror = { version = "1", optional = true }
merlin = { version = "3", default-features = false }
clear_on_drop = { version = "0.2", default-features = false }
zeroize = "1.8.1"

[dev-dependencies]
hex = "0.3"
Expand All @@ -42,7 +42,7 @@ curve25519-dalek = { version = "4.1.1", features = ["digest", "group", "legacy_c
default = ["std"]
yoloproofs = []
std = ["rand", "rand/std", "rand/std_rng", "thiserror"]
nightly = ["subtle/nightly", "clear_on_drop/nightly"]
nightly = ["subtle/nightly"]
docs = ["nightly"]


Expand Down
56 changes: 9 additions & 47 deletions src/range_proof/party.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
extern crate alloc;

use alloc::vec::Vec;
use clear_on_drop::clear::Clear;
use zeroize::ZeroizeOnDrop;
use core::iter;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
Expand Down Expand Up @@ -61,8 +61,11 @@ impl Party {
}

/// A party waiting for the dealer to assign their position in the aggregation.
#[derive(ZeroizeOnDrop)]
pub struct PartyAwaitingPosition<'a> {
#[zeroize(skip)]
bp_gens: &'a BulletproofGens,
#[zeroize(skip)]
pc_gens: &'a PedersenGens,
n: usize,
v: u64,
Expand Down Expand Up @@ -106,7 +109,7 @@ impl<'a> PartyAwaitingPosition<'a> {
// If v_i = 1, we add a_L[i] * G[i] + a_R[i] * H[i] = G[i]
let v_i = Choice::from(((self.v >> i) & 1) as u8);
let mut point = -H_i;
let point = RistrettoPoint::conditional_select(&point, G_i, v_i);
point = RistrettoPoint::conditional_select(&point, G_i, v_i);
A += point;
i += 1;
}
Expand Down Expand Up @@ -145,21 +148,15 @@ impl<'a> PartyAwaitingPosition<'a> {
}
}

/// Overwrite secrets with null bytes when they go out of scope.
impl<'a> Drop for PartyAwaitingPosition<'a> {
fn drop(&mut self) {
self.v.clear();
self.v_blinding.clear();
}
}

/// A party which has committed to the bits of its value
/// and is waiting for the aggregated value challenge from the dealer.
#[derive(ZeroizeOnDrop)]
pub struct PartyAwaitingBitChallenge<'a> {
n: usize, // bitsize of the range
v: u64,
v_blinding: Scalar,
j: usize,
#[zeroize(skip)]
pc_gens: &'a PedersenGens,
a_blinding: Scalar,
s_blinding: Scalar,
Expand Down Expand Up @@ -238,30 +235,9 @@ impl<'a> PartyAwaitingBitChallenge<'a> {
}
}

/// Overwrite secrets with null bytes when they go out of scope.
impl<'a> Drop for PartyAwaitingBitChallenge<'a> {
fn drop(&mut self) {
self.v.clear();
self.v_blinding.clear();
self.a_blinding.clear();
self.s_blinding.clear();

// Important: due to how ClearOnDrop auto-implements InitializableFromZeroed
// for T: Default, calling .clear() on Vec compiles, but does not
// clear the content. Instead, it only clears the Vec's header.
// Clearing the underlying buffer item-by-item will do the job, but will
// keep the header as-is, which is fine since the header does not contain secrets.
for e in self.s_L.iter_mut() {
e.clear();
}
for e in self.s_R.iter_mut() {
e.clear();
}
}
}

/// A party which has committed to their polynomial coefficents
/// and is waiting for the polynomial challenge from the dealer.
#[derive(ZeroizeOnDrop)]
pub struct PartyAwaitingPolyChallenge {
offset_zz: Scalar,
l_poly: util::VecPoly1,
Expand Down Expand Up @@ -304,18 +280,4 @@ impl PartyAwaitingPolyChallenge {
r_vec,
})
}
}

/// Overwrite secrets with null bytes when they go out of scope.
impl Drop for PartyAwaitingPolyChallenge {
fn drop(&mut self) {
self.v_blinding.clear();
self.a_blinding.clear();
self.s_blinding.clear();
self.t_1_blinding.clear();
self.t_2_blinding.clear();

// Note: polynomials r_poly, l_poly and t_poly
// are cleared within their own Drop impls.
}
}
}
64 changes: 10 additions & 54 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ extern crate alloc;

use alloc::vec;
use alloc::vec::Vec;
use clear_on_drop::clear::Clear;
use curve25519_dalek::scalar::Scalar;
use zeroize::ZeroizeOnDrop;

use crate::inner_product_proof::inner_product;

/// Represents a degree-1 vector polynomial \\(\mathbf{a} + \mathbf{b} \cdot x\\).
#[derive(ZeroizeOnDrop)]
pub struct VecPoly1(pub Vec<Scalar>, pub Vec<Scalar>);

/// Represents a degree-3 vector polynomial
/// \\(\mathbf{a} + \mathbf{b} \cdot x + \mathbf{c} \cdot x^2 + \mathbf{d} \cdot x^3 \\).
#[cfg(feature = "yoloproofs")]
#[derive(ZeroizeOnDrop)]
pub struct VecPoly3(
pub Vec<Scalar>,
pub Vec<Scalar>,
Expand All @@ -24,6 +26,7 @@ pub struct VecPoly3(
);

/// Represents a degree-2 scalar polynomial \\(a + b \cdot x + c \cdot x^2\\)
#[derive(ZeroizeOnDrop)]
pub struct Poly2(pub Scalar, pub Scalar, pub Scalar);

/// Represents a degree-6 scalar polynomial, without the zeroth degree
Expand Down Expand Up @@ -161,61 +164,13 @@ impl Poly2 {
}

#[cfg(feature = "yoloproofs")]
#[derive(ZeroizeOnDrop)]
impl Poly6 {
pub fn eval(&self, x: Scalar) -> Scalar {
x * (self.t1 + x * (self.t2 + x * (self.t3 + x * (self.t4 + x * (self.t5 + x * self.t6)))))
}
}

impl Drop for VecPoly1 {
fn drop(&mut self) {
for e in self.0.iter_mut() {
e.clear();
}
for e in self.1.iter_mut() {
e.clear();
}
}
}

impl Drop for Poly2 {
fn drop(&mut self) {
self.0.clear();
self.1.clear();
self.2.clear();
}
}

#[cfg(feature = "yoloproofs")]
impl Drop for VecPoly3 {
fn drop(&mut self) {
for e in self.0.iter_mut() {
e.clear();
}
for e in self.1.iter_mut() {
e.clear();
}
for e in self.2.iter_mut() {
e.clear();
}
for e in self.3.iter_mut() {
e.clear();
}
}
}

#[cfg(feature = "yoloproofs")]
impl Drop for Poly6 {
fn drop(&mut self) {
self.t1.clear();
self.t2.clear();
self.t3.clear();
self.t4.clear();
self.t5.clear();
self.t6.clear();
}
}

/// Raises `x` to the power `n` using binary exponentiation,
/// with (1 to 2)*lg(n) scalar multiplications.
/// TODO: a consttime version of this would be awfully similar to a Montgomery ladder.
Expand Down Expand Up @@ -269,6 +224,7 @@ pub fn read32(data: &[u8]) -> [u8; 32] {

#[cfg(test)]
mod tests {
use zeroize::Zeroize;
use super::*;

#[test]
Expand Down Expand Up @@ -355,7 +311,7 @@ mod tests {
let mut v = vec![Scalar::from(24u64), Scalar::from(42u64)];

for e in v.iter_mut() {
e.clear();
e.zeroize();
}

fn flat_slice<T>(x: &[T]) -> &[u8] {
Expand All @@ -378,9 +334,9 @@ mod tests {
Scalar::from(255u64),
);

v.0.clear();
v.1.clear();
v.2.clear();
v.0.zeroize();
v.1.zeroize();
v.2.zeroize();

fn as_bytes<T>(x: &T) -> &[u8] {
use core::mem;
Expand Down