Skip to content

Commit

Permalink
Merge pull request dalek-cryptography#330 from fmiguelgarcia/main
Browse files Browse the repository at this point in the history
  • Loading branch information
quackzar committed Nov 1, 2022
2 parents df6c41b + be11c80 commit eb74e85
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 95 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

Entries are listed in reverse chronological order.

## 4.0.1
* `Serde` is optional.
* Adds new backends for `curve25519-dalek`: `u32_backend`, `u64_backend`,
and `avx2_backend`(default on `std`).
* Replace `clear_on_drop` by `zeroize`.

## 4.0.0

* Update to `rand_core` `0.6`. This requires a major version bump but the API
Expand Down
25 changes: 16 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name = "bulletproofs"
# - update version field
# - update html_root_url
# - update CHANGELOG
version = "4.0.0"
version = "4.0.1"
authors = ["Cathie Yun <cathieyun@gmail.com>",
"Henry de Valence <hdevalence@hdevalence.ca>",
"Oleg Andreev <oleganza@gmail.com>"]
Expand All @@ -24,11 +24,11 @@ digest = { version = "0.9.0", default-features = false }
rand_core = { version = "0.6", default-features = false, features = ["alloc"] }
rand = { version = "0.8", default-features = false, optional = true }
byteorder = { version = "1", default-features = false }
serde = { version = "1", default-features = false, features = ["alloc"] }
serde_derive = { version = "1", default-features = false }
serde = { version = "1", default-features = false, features = ["alloc"], optional = true }
serde_derive = { version = "1", default-features = false, optional = true }
thiserror = { version = "1", optional = true }
merlin = { version = "3", default-features = false }
clear_on_drop = { version = "0.2", default-features = false }
zeroize = { version = "1", default-features = false, features = ["alloc"], optional = true }

[dev-dependencies]
hex = "0.3"
Expand All @@ -37,13 +37,20 @@ bincode = "1"
rand_chacha = "0.3"

[features]
default = ["std"]
avx2_backend = ["curve25519-dalek/avx2_backend"]
default = ["std", "u64_backend", "zeroize"]

u64_backend = ["curve25519-dalek/u64_backend", ]
simd_backend = ["curve25519-dalek/simd_backend"]
u32_backend = ["curve25519-dalek/u32_backend"]
yoloproofs = []
std = ["rand", "rand/std", "rand/std_rng", "thiserror", "curve25519-dalek/std"]
nightly = ["curve25519-dalek/nightly", "curve25519-dalek/alloc", "subtle/nightly", "clear_on_drop/nightly"]
docs = ["nightly"]

std = [
"serde",
"serde_derive",
"curve25519-dalek/serde",
"rand/std",
"thiserror",
]

[[test]]
name = "range_proof"
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

extern crate alloc;

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde_derive;

Expand Down
44 changes: 15 additions & 29 deletions src/r1cs/prover.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#![allow(non_snake_case)]

use clear_on_drop::clear::Clear;
use core::borrow::BorrowMut;
use core::mem;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::{Identity, MultiscalarMul};
use merlin::Transcript;
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;

use super::{
ConstraintSystem, LinearCombination, R1CSProof, RandomizableConstraintSystem,
Expand Down Expand Up @@ -72,26 +73,15 @@ pub struct RandomizingProver<'g, T: BorrowMut<Transcript>> {
}

/// Overwrite secrets with null bytes when they go out of scope.
impl Drop for Secrets {
#[cfg(feature = "zeroize")]
impl<'t, 'g> Drop for Prover<'t, 'g> {
fn drop(&mut self) {
self.v.clear();
self.v_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.a_L.iter_mut() {
e.clear();
}
for e in self.a_R.iter_mut() {
e.clear();
}
for e in self.a_O.iter_mut() {
e.clear();
}
// XXX use ClearOnDrop instead of doing the above
self.v.zeroize();
self.v_blinding.zeroize();

self.a_L.zeroize();
self.a_R.zeroize();
self.a_O.zeroize();
}
}

Expand Down Expand Up @@ -697,16 +687,12 @@ impl<'g, T: BorrowMut<Transcript>> Prover<'g, T> {
r_vec,
);

// We do not yet have a ClearOnDrop wrapper for Vec<Scalar>.
// When PR 202 [1] is merged, we can simply wrap s_L and s_R at the point of creation.
// [1] https://github.com/dalek-cryptography/curve25519-dalek/pull/202
for scalar in s_L1
.iter_mut()
.chain(s_L2.iter_mut())
.chain(s_R1.iter_mut())
.chain(s_R2.iter_mut())
#[cfg(feature = "zeroize")]
{
scalar.clear();
s_L1.zeroize();
s_L2.zeroize();
s_R1.zeroize();
s_R2.zeroize();
}
let proof = R1CSProof {
A_I1,
Expand Down
15 changes: 10 additions & 5 deletions src/range_proof/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,41 @@ use curve25519_dalek::scalar::Scalar;
use crate::generators::{BulletproofGens, PedersenGens};

/// A commitment to the bits of a party's value.
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BitCommitment {
pub(super) V_j: CompressedRistretto,
pub(super) A_j: RistrettoPoint,
pub(super) S_j: RistrettoPoint,
}

/// Challenge values derived from all parties' [`BitCommitment`]s.
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BitChallenge {
pub(super) y: Scalar,
pub(super) z: Scalar,
}

/// A commitment to a party's polynomial coefficents.
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PolyCommitment {
pub(super) T_1_j: RistrettoPoint,
pub(super) T_2_j: RistrettoPoint,
}

/// Challenge values derived from all parties' [`PolyCommitment`]s.
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PolyChallenge {
pub(super) x: Scalar,
}

/// A party's proof share, ready for aggregation into the final
/// [`RangeProof`](::RangeProof).
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ProofShare {
pub(super) t_x: Scalar,
pub(super) t_x_blinding: Scalar,
Expand Down
7 changes: 5 additions & 2 deletions src/range_proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ use crate::transcript::TranscriptProtocol;
use crate::util;

use rand_core::{CryptoRng, RngCore};
use serde::de::Visitor;
use serde::{self, Deserialize, Deserializer, Serialize, Serializer};

#[cfg(feature = "serde")]
use serde::{self, de::Visitor, Deserialize, Deserializer, Serialize, Serializer};

// Modules for MPC protocol

Expand Down Expand Up @@ -538,6 +539,7 @@ impl RangeProof {
}
}

#[cfg(feature = "serde")]
impl Serialize for RangeProof {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -547,6 +549,7 @@ impl Serialize for RangeProof {
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for RangeProof {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down
43 changes: 19 additions & 24 deletions src/range_proof/party.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
extern crate alloc;

use alloc::vec::Vec;
use clear_on_drop::clear::Clear;
use core::iter;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::traits::MultiscalarMul;
use rand_core::{CryptoRng, RngCore};
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;

use crate::errors::MPCError;
use crate::generators::{BulletproofGens, PedersenGens};
Expand Down Expand Up @@ -145,10 +146,11 @@ impl<'a> PartyAwaitingPosition<'a> {
}

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

Expand Down Expand Up @@ -238,24 +240,16 @@ impl<'a> PartyAwaitingBitChallenge<'a> {
}

/// Overwrite secrets with null bytes when they go out of scope.
#[cfg(feature = "zeroize")]
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();
}
self.v.zeroize();
self.v_blinding.zeroize();
self.a_blinding.zeroize();
self.s_blinding.zeroize();

self.s_L.zeroize();
self.s_R.zeroize();
}
}

Expand Down Expand Up @@ -306,13 +300,14 @@ impl PartyAwaitingPolyChallenge {
}

/// Overwrite secrets with null bytes when they go out of scope.
#[cfg(feature = "zeroize")]
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();
self.v_blinding.zeroize();
self.a_blinding.zeroize();
self.s_blinding.zeroize();
self.t_1_blinding.zeroize();
self.t_2_blinding.zeroize();

// Note: polynomials r_poly, l_poly and t_poly
// are cleared within their own Drop impls.
Expand Down
38 changes: 12 additions & 26 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ extern crate alloc;

use alloc::vec;
use alloc::vec::Vec;
use clear_on_drop::clear::Clear;
use curve25519_dalek::scalar::Scalar;
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;

use crate::inner_product_proof::inner_product;

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

/// Represents a degree-3 vector polynomial
Expand All @@ -24,6 +26,7 @@ pub struct VecPoly3(
);

/// Represents a degree-2 scalar polynomial \\(a + b \cdot x + c \cdot x^2\\)
#[cfg_attr(feature = "zeroize", derive(Zeroize), zeroize(drop))]
pub struct Poly2(pub Scalar, pub Scalar, pub Scalar);

/// Represents a degree-6 scalar polynomial, without the zeroth degree
Expand Down Expand Up @@ -167,25 +170,6 @@ impl Poly6 {
}
}

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) {
Expand Down Expand Up @@ -350,12 +334,13 @@ mod tests {
assert_eq!(sum_of_powers_slow(&x, 6), Scalar::from(111111u64));
}

#[cfg(feature = "zeroize")]
#[test]
fn vec_of_scalars_clear_on_drop() {
fn vec_of_scalars_zeroize() {
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 @@ -370,17 +355,18 @@ mod tests {
assert_eq!(v[1], Scalar::zero());
}

#[cfg(feature = "zeroize")]
#[test]
fn tuple_of_scalars_clear_on_drop() {
fn tuple_of_scalars_zeroize() {
let mut v = Poly2(
Scalar::from(24u64),
Scalar::from(42u64),
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

0 comments on commit eb74e85

Please sign in to comment.