Skip to content

Commit eb8c5a6

Browse files
committed
Use zeroize to zero memory of sensitive objects on Drop, remove un-necessary member from Saver subprotocol, more docs and several refactorings
Signed-off-by: lovesh <lovesh.bond@gmail.com>
1 parent e9e9253 commit eb8c5a6

File tree

31 files changed

+508
-127
lines changed

31 files changed

+508
-127
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Library providing privacy enhancing cryptographic primitives.
1111
1. [Schnorr proof of knowledge protocol](./schnorr_pok) to prove knowledge of discrete log. [This](https://crypto.stanford.edu/cs355/19sp/lec5.pdf) is a good reference.
1212
2. [BBS+ signature](./bbs_plus) for anonymous credentials. Based on the paper [Anonymous Attestation Using the Strong Diffie Hellman Assumption Revisited](https://eprint.iacr.org/2016/663)
1313
3. [Dynamic accumulators, both positive and universal](./vb_accumulator). Based on the paper [Dynamic Universal Accumulator with Batch Update over Bilinear Groups](https://eprint.iacr.org/2020/777)
14-
4. [Proof system](./proof_system) that combines above primitives for use cases like prove knowledge of a BBS+ signature and the corresponding messages and the (non)membership of a certain message in the accumulator.
14+
4. [Composite proof system](./proof_system) that combines above primitives for use cases like prove knowledge of a BBS+ signature and the corresponding messages and the (non)membership of a certain message(s) in the accumulator. Also numeric bounds (min, max) on the messages can be proved in zero-knowledge and verifiable encryption of messages is also supported.
1515
5. [Verifiable encryption](./saver) using [SAVER](https://eprint.iacr.org/2019/1270).
1616
6. [Compression and amortization of Sigma protocols](./compressed_sigma). This is PoC implementation.
1717

bbs_plus/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bbs_plus"
3-
version = "0.6.0"
3+
version = "0.7.0"
44
edition = "2021"
55
authors = ["Dock.io"]
66
license = "Apache-2.0"
@@ -18,10 +18,11 @@ ark-ec = { version = "^0.3.0", default-features = false }
1818
ark-std = { version = "^0.3.0", default-features = false }
1919
digest = "0.9"
2020
rayon = { version = "1", optional = true }
21-
schnorr_pok = { version = "0.5.0", default-features = false, path = "../schnorr_pok" }
21+
schnorr_pok = { version = "0.6.0", default-features = false, path = "../schnorr_pok" }
2222
dock_crypto_utils = { version = "0.4.0", default-features = false, path = "../utils" }
2323
serde = { version = "1.0", default-features = false, features = ["derive"] }
2424
serde_with = { version = "1.10.0", default-features = false, features = ["macros"] }
25+
zeroize = { version = "1.5.5", features = ["derive"] }
2526

2627
[dev-dependencies]
2728
blake2 = { version = "0.9", default-features = false }

bbs_plus/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ Provides
55
- signature creation and verification in both groups G1 and G2.
66
- proof of knowledge of signature and corresponding messages in group G1 as that is more efficient.
77

8+
### Modules
9+
10+
1. Signature parameters and key generation module - [`setup`]
11+
2. Signature module - [`signature`]
12+
3. Proof of knowledge of signature module - [`proof`]
13+
814
The implementation tries to use the same variable names as the paper and thus violate Rust's naming conventions at places.
915

16+
[`setup`]: crate::setup
17+
[`signature`]: crate::signature
18+
[`proof`]: crate::proof
19+
1020
License: Apache-2.0

bbs_plus/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,17 @@
66
//! - signature creation and verification in both groups G1 and G2.
77
//! - proof of knowledge of signature and corresponding messages in group G1 as that is more efficient.
88
//!
9+
//! ## Modules
10+
//!
11+
//! 1. Signature parameters and key generation module - [`setup`]
12+
//! 2. Signature module - [`signature`]
13+
//! 3. Proof of knowledge of signature module - [`proof`]
14+
//!
915
//! The implementation tries to use the same variable names as the paper and thus violate Rust's naming conventions at places.
16+
//!
17+
//! [`setup`]: crate::setup
18+
//! [`signature`]: crate::signature
19+
//! [`proof`]: crate::proof
1020
1121
pub mod error;
1222
pub mod proof;

bbs_plus/src/proof.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
//! Proof of knowledge of the signature and corresponding messages as per section 4.5 of the paper
2-
//! <https://eprint.iacr.org/2016/663.pdf>
32
//! # Examples
43
//!
54
//! Creating proof of knowledge of signature and verifying it:
@@ -14,12 +13,23 @@
1413
//! let params_g1 = SignatureParamsG1::<Bls12_381>::generate_using_rng(&mut rng, 5);
1514
//! let keypair_g2 = KeypairG2::<Bls12_381>::generate(&mut rng, &params_g1);
1615
//!
16+
//! let pk_g2 = &keypair_g2.public_key;
17+
//!
18+
//! // Verifiers should check that the signature parameters and public key are valid before verifying
19+
//! // any signatures. This just needs to be done once when the verifier fetches/receives them.
20+
//!
21+
//! assert!(params_g1.is_valid());
22+
//! assert!(pk_g2.is_valid());
23+
//!
1724
//! // `messages` contains elements of the scalar field
1825
//! let sig_g1 = SignatureG1::<Bls12_381>::new(&mut rng, &messages, &keypair_g2.secret_key, &params_g1).unwrap();
26+
//!
1927
//! let mut blindings = BTreeMap::new();
2028
//! let mut revealed_indices = BTreeSet::new();
21-
//! // Populate blindings with message index and corresponding blinding
22-
//! // Populate revealed_indices with 0-based indices of revealed messages
29+
//!
30+
//! // Populate `blindings` with message index and corresponding blinding
31+
//! // Populate `revealed_indices` with 0-based indices of revealed messages
32+
//!
2333
//! let pok = PoKOfSignatureG1Protocol::init(
2434
//! &mut rng,
2535
//! &sig_g1,
@@ -38,7 +48,7 @@
3848
//! .verify(
3949
//! &revealed_msgs,
4050
//! &challenge,
41-
//! &keypair_g2.public_key,
51+
//! pk_g2,
4252
//! &params_g1,
4353
//! )
4454
//! .unwrap();
@@ -67,6 +77,7 @@ use schnorr_pok::{error::SchnorrError, SchnorrCommitment, SchnorrResponse};
6777
use serde::{Deserialize, Serialize};
6878
use serde_with::serde_as;
6979
pub use serialization::*;
80+
use zeroize::Zeroize;
7081

7182
/// Proof of knowledge of BBS+ signature in group G1
7283
/// The BBS+ signature proves validity of a set of messages {m_i}, i in I. This stateful protocol proves knowledge of such
@@ -334,11 +345,28 @@ where
334345
}
335346
}
336347

348+
impl<E: PairingEngine> Zeroize for PoKOfSignatureG1Protocol<E> {
349+
fn zeroize(&mut self) {
350+
// Other members of `self` are public anyway
351+
self.sc_comm_1.zeroize();
352+
self.sc_wits_1.zeroize();
353+
self.sc_comm_2.zeroize();
354+
self.sc_wits_2.zeroize();
355+
}
356+
}
357+
358+
impl<E: PairingEngine> Drop for PoKOfSignatureG1Protocol<E> {
359+
fn drop(&mut self) {
360+
self.zeroize();
361+
}
362+
}
363+
337364
impl<E> PoKOfSignatureG1Proof<E>
338365
where
339366
E: PairingEngine,
340367
{
341-
/// Verify if the proof is valid
368+
/// Verify if the proof is valid. Assumes that the public key and parameters have been
369+
/// validated already.
342370
pub fn verify(
343371
&self,
344372
revealed_msgs: &BTreeMap<usize, E::Fr>,
@@ -675,22 +703,23 @@ mod tests {
675703
let proof = pok.gen_proof(&challenge_prover).unwrap();
676704
proof_create_duration += start.elapsed();
677705

706+
let public_key = &keypair.public_key;
707+
assert!(params.is_valid());
708+
assert!(public_key.is_valid());
709+
678710
let mut chal_bytes_verifier = vec![];
679711
proof
680712
.challenge_contribution(&revealed_msgs, &params, &mut chal_bytes_verifier)
681713
.unwrap();
682714
let challenge_verifier =
683715
compute_random_oracle_challenge::<Fr, Blake2b>(&chal_bytes_verifier);
684716

717+
assert_eq!(chal_bytes_prover, chal_bytes_verifier);
718+
685719
let mut proof_verif_duration = Duration::default();
686720
let start = Instant::now();
687721
proof
688-
.verify(
689-
&revealed_msgs,
690-
&challenge_verifier,
691-
&keypair.public_key,
692-
&params,
693-
)
722+
.verify(&revealed_msgs, &challenge_verifier, public_key, &params)
694723
.unwrap();
695724
proof_verif_duration += start.elapsed();
696725

bbs_plus/src/setup.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use ark_std::{
4444
};
4545
use digest::{BlockInput, Digest, FixedOutput, Reset, Update};
4646
use schnorr_pok::{error::SchnorrError, impl_proof_of_knowledge_of_discrete_log};
47+
use zeroize::Zeroize;
4748

4849
use dock_crypto_utils::hashing_utils::{
4950
field_elem_from_seed, projective_group_elem_from_try_and_incr,
@@ -58,10 +59,24 @@ use serde_with::serde_as;
5859
/// Secret key used by the signer to sign messages
5960
#[serde_as]
6061
#[derive(
61-
Clone, PartialEq, Eq, Debug, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
62+
Clone,
63+
PartialEq,
64+
Eq,
65+
Debug,
66+
CanonicalSerialize,
67+
CanonicalDeserialize,
68+
Serialize,
69+
Deserialize,
70+
Zeroize,
6271
)]
6372
pub struct SecretKey<F: PrimeField + SquareRootField>(#[serde_as(as = "FieldBytes")] pub F);
6473

74+
impl<F: PrimeField + SquareRootField> Drop for SecretKey<F> {
75+
fn drop(&mut self) {
76+
self.zeroize();
77+
}
78+
}
79+
6580
// TODO: Add "prepared" version of public key
6681

6782
impl<F: PrimeField + SquareRootField> SecretKey<F> {
@@ -166,7 +181,9 @@ macro_rules! impl_sig_params {
166181
}
167182
}
168183

169-
/// Check that all group elements are non-zero (returns false if any element is zero)
184+
/// Check that all group elements are non-zero (returns false if any element is zero).
185+
/// A verifier on receiving these parameters must first check that they are valid and only
186+
/// then use them for any signature or proof of knowledge of signature verification.
170187
pub fn is_valid(&self) -> bool {
171188
!(self.g1.is_zero()
172189
|| self.g2.is_zero()
@@ -274,7 +291,8 @@ macro_rules! impl_public_key {
274291
Self(params.g2.mul(secret_key.0.into_repr()).into())
275292
}
276293

277-
/// Public key shouldn't be 0
294+
/// Public key shouldn't be 0. A verifier on receiving this must first check that its
295+
/// valid and only then use it for any signature or proof of knowledge of signature verification.
278296
pub fn is_valid(&self) -> bool {
279297
!self.0.is_zero()
280298
}
@@ -300,6 +318,18 @@ macro_rules! impl_keypair {
300318
pub public_key: $pk<E>,
301319
}
302320

321+
impl<E: PairingEngine> Zeroize for $name<E> {
322+
fn zeroize(&mut self) {
323+
self.secret_key.zeroize();
324+
}
325+
}
326+
327+
impl<E: PairingEngine> Drop for $name<E> {
328+
fn drop(&mut self) {
329+
self.zeroize();
330+
}
331+
}
332+
303333
/// Create a secret key and corresponding public key
304334
impl<E: PairingEngine> $name<E> {
305335
pub fn generate_using_seed<D>(seed: &[u8], params: &$params<E>) -> Self
@@ -366,8 +396,8 @@ mod tests {
366396
let keypair = $keypair::<Bls12_381>::generate_using_rng(&mut $rng, &params);
367397
test_serialization!($keypair<Bls12_381>, keypair);
368398

369-
let pk = keypair.public_key;
370-
let sk = keypair.secret_key;
399+
let pk = keypair.public_key.clone();
400+
let sk = keypair.secret_key.clone();
371401
test_serialization!($public_key<Bls12_381>, pk);
372402
test_serialization!(SecretKey<<Bls12_381 as PairingEngine>::Fr>, sk);
373403
};
@@ -405,10 +435,12 @@ mod tests {
405435
assert_eq!(
406436
keypair,
407437
$keypair {
408-
secret_key: sk,
438+
secret_key: sk.clone(),
409439
public_key: pk
410440
}
411441
);
442+
drop(sk);
443+
drop(keypair);
412444
};
413445
}
414446

0 commit comments

Comments
 (0)