Skip to content

Commit

Permalink
zeroize on drop ecies' private key (#814)
Browse files Browse the repository at this point in the history
  • Loading branch information
benr-ml authored Jul 18, 2024
1 parent 650917b commit a3d5b18
Show file tree
Hide file tree
Showing 13 changed files with 57 additions and 19 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion fastcrypto-tbls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "Threshold BLS and DKG protocols"
repository = "https://github.com/MystenLabs/fastcrypto"

[dependencies]
fastcrypto = { path = "../fastcrypto", features = ["aes"]}
fastcrypto = { path = "../fastcrypto", features = ["aes"] }

rand.workspace = true
serde.workspace = true
Expand All @@ -18,6 +18,7 @@ sha3.workspace = true
digest.workspace = true
bcs.workspace = true
tracing.workspace = true
zeroize.workspace = true

itertools = "0.10.5"
hex = "0.4.3"
Expand Down
6 changes: 5 additions & 1 deletion fastcrypto-tbls/src/dkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ use crate::random_oracle::RandomOracle;
use crate::tbls::Share;
use fastcrypto::groups::GroupElement;
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;

/// Generics below use `G: GroupElement' for the group of the VSS public key, and `EG: GroupElement'
/// for the group of the ECIES public key.
/// Party in the DKG protocol.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Party<G: GroupElement, EG: GroupElement> {
pub struct Party<G: GroupElement, EG: GroupElement>
where
EG::ScalarType: Zeroize,
{
pub id: PartyId,
pub(crate) nodes: Nodes<EG>,
pub t: u16,
Expand Down
5 changes: 3 additions & 2 deletions fastcrypto-tbls/src/dkg_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::ecies::RecoveryPackage;
use crate::ecies_v0::MultiRecipientEncryption;
use tap::prelude::*;
use tracing::{debug, error, info, warn};
use zeroize::Zeroize;

/// [Message] holds all encrypted shares a dealer sends during the first phase of the
/// protocol.
Expand Down Expand Up @@ -102,7 +103,7 @@ impl<G, EG> Party<G, EG>
where
G: GroupElement + MultiScalarMul + Serialize + DeserializeOwned,
EG: GroupElement + Serialize + DeserializeOwned,
EG::ScalarType: FiatShamirChallenge,
EG::ScalarType: FiatShamirChallenge + Zeroize,
{
/// 1. Create a new ECIES private key and send the public key to all parties.
/// 2. After *all* parties have sent their ECIES public keys, create the (same) set of nodes.
Expand Down Expand Up @@ -717,7 +718,7 @@ where
pub fn create_fake_complaint<EG>() -> Complaint<EG>
where
EG: GroupElement + Serialize + DeserializeOwned,
<EG as GroupElement>::ScalarType: FiatShamirChallenge,
<EG as GroupElement>::ScalarType: FiatShamirChallenge + Zeroize,
{
let sk = ecies::PrivateKey::<EG>::new(&mut rand::thread_rng());
let pk = ecies::PublicKey::<EG>::from_private_key(&sk);
Expand Down
3 changes: 2 additions & 1 deletion fastcrypto-tbls/src/dkg_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{ecies, ecies_v1};

use tap::prelude::*;
use tracing::{debug, error, info, warn};
use zeroize::Zeroize;

// TODO: Move Party, Complaint, Confirmation, Output here and remove old APIs

Expand Down Expand Up @@ -103,7 +104,7 @@ impl<G, EG> Party<G, EG>
where
G: GroupElement + MultiScalarMul + Serialize + DeserializeOwned,
EG: GroupElement + Serialize + HashToGroupElement + DeserializeOwned,
EG::ScalarType: FiatShamirChallenge,
EG::ScalarType: FiatShamirChallenge + Zeroize,
{
/// 1. Create a new ECIES private key and send the public key to all parties.
/// 2. After *all* parties have sent their ECIES public keys, create the (same) set of nodes.
Expand Down
8 changes: 5 additions & 3 deletions fastcrypto-tbls/src/ecies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
use crate::nizk::DdhTupleNizk;
use fastcrypto::groups::GroupElement;
use serde::{Deserialize, Serialize};
use zeroize::{Zeroize, ZeroizeOnDrop};

// TODO: Use ZeroizeOnDrop.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PrivateKey<G: GroupElement>(pub(crate) G::ScalarType);
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ZeroizeOnDrop)]
pub struct PrivateKey<G: GroupElement>(pub(crate) G::ScalarType)
where
G::ScalarType: Zeroize;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PublicKey<G: GroupElement>(pub(crate) G);
Expand Down
5 changes: 3 additions & 2 deletions fastcrypto-tbls/src/ecies_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use fastcrypto::traits::{AllowedRng, ToFromBytes};
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use typenum::consts::{U16, U32};
use zeroize::Zeroize;

///
/// Simple ECIES encryption using a generic group and AES-256-counter.
Expand Down Expand Up @@ -40,7 +41,7 @@ pub struct MultiRecipientEncryption<G: GroupElement>(G, Vec<Vec<u8>>, DLNizk<G>)
impl<G> PrivateKey<G>
where
G: GroupElement + Serialize,
<G as GroupElement>::ScalarType: FiatShamirChallenge,
<G as GroupElement>::ScalarType: FiatShamirChallenge + Zeroize,
{
pub fn new<R: AllowedRng>(rng: &mut R) -> Self {
Self(G::ScalarType::rand(rng))
Expand Down Expand Up @@ -80,7 +81,7 @@ where
impl<G> PublicKey<G>
where
G: GroupElement + Serialize + DeserializeOwned,
<G as GroupElement>::ScalarType: FiatShamirChallenge,
<G as GroupElement>::ScalarType: FiatShamirChallenge + Zeroize,
{
pub fn from_private_key(sk: &PrivateKey<G>) -> Self {
Self(G::generator() * sk.0)
Expand Down
3 changes: 2 additions & 1 deletion fastcrypto-tbls/src/ecies_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use fastcrypto::traits::{AllowedRng, ToFromBytes};
use serde::{Deserialize, Serialize};
use typenum::consts::{U16, U32};
use typenum::Unsigned;
use zeroize::Zeroize;

/// Simple ECIES encryption using a generic group and AES-256-counter.
///
Expand All @@ -34,7 +35,7 @@ pub struct MultiRecipientEncryption<G: GroupElement> {

impl<G: GroupElement + Serialize> MultiRecipientEncryption<G>
where
<G as GroupElement>::ScalarType: FiatShamirChallenge,
<G as GroupElement>::ScalarType: FiatShamirChallenge + Zeroize,
G: HashToGroupElement,
{
pub fn encrypt<R: AllowedRng>(
Expand Down
5 changes: 3 additions & 2 deletions fastcrypto-tbls/src/nidkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ use itertools::izip;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::collections::HashMap;
use std::num::NonZeroU16;
use zeroize::Zeroize;

/// Party in the DKG protocol.
pub struct Party<G: GroupElement>
where
G::ScalarType: Serialize + DeserializeOwned,
G::ScalarType: Serialize + DeserializeOwned + Zeroize,
{
id: PartyId,
nodes: Nodes<G>,
Expand Down Expand Up @@ -83,7 +84,7 @@ pub struct Complaint<G: GroupElement> {
impl<G> Party<G>
where
G: GroupElement + MultiScalarMul + Serialize + DeserializeOwned,
<G as GroupElement>::ScalarType: Serialize + DeserializeOwned + FiatShamirChallenge,
<G as GroupElement>::ScalarType: Serialize + DeserializeOwned + FiatShamirChallenge + Zeroize,
{
/// 1. Create a new private key and send the public key to all parties.
///
Expand Down
7 changes: 4 additions & 3 deletions fastcrypto-tbls/src/tests/ecies_v0_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ const MSG: &[u8; 4] = b"test";
mod point_tests {
use super::*;
use crate::ecies::{PrivateKey, PublicKey};
use zeroize::Zeroize;

#[test]
fn test_decryption<Group: GroupElement + Serialize + DeserializeOwned>()
where
Group::ScalarType: FiatShamirChallenge,
Group::ScalarType: FiatShamirChallenge + Zeroize,
{
let sk = PrivateKey::<Group>::new(&mut thread_rng());
let pk = PublicKey::<Group>::from_private_key(&sk);
Expand All @@ -35,7 +36,7 @@ mod point_tests {
#[test]
fn test_recovery_package<Group: GroupElement + Serialize + DeserializeOwned>()
where
Group::ScalarType: FiatShamirChallenge,
Group::ScalarType: FiatShamirChallenge + Zeroize,
{
let sk = PrivateKey::<Group>::new(&mut thread_rng());
let pk = PublicKey::<Group>::from_private_key(&sk);
Expand All @@ -62,7 +63,7 @@ mod point_tests {
#[test]
fn test_multi_rec<Group: GroupElement + Serialize + DeserializeOwned>()
where
Group::ScalarType: FiatShamirChallenge,
Group::ScalarType: FiatShamirChallenge + Zeroize,
{
let ro = RandomOracle::new("test");
let keys_and_msg = (0..10u32)
Expand Down
20 changes: 18 additions & 2 deletions fastcrypto-tbls/src/tests/ecies_v1_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::ecies::{PrivateKey, PublicKey};
use crate::ecies_v1::*;
use crate::random_oracle::RandomOracle;
use fastcrypto::bls12381::min_sig::BLS12381KeyPair;
use fastcrypto::groups::bls12381::{G1Element, G2Element, Scalar};
use fastcrypto::groups::bls12381::{G1Element, G2Element, Scalar, SCALAR_LENGTH};
use fastcrypto::groups::{FiatShamirChallenge, GroupElement};
use fastcrypto::traits::KeyPair;
use rand::thread_rng;
Expand All @@ -17,11 +17,12 @@ mod point_tests {
use super::*;
use crate::ecies::{PrivateKey, PublicKey};
use fastcrypto::groups::HashToGroupElement;
use zeroize::Zeroize;

#[test]
fn test_multi_rec<Group: GroupElement + Serialize + DeserializeOwned>()
where
Group::ScalarType: FiatShamirChallenge,
Group::ScalarType: FiatShamirChallenge + Zeroize,
Group: HashToGroupElement,
{
let ro = RandomOracle::new("test");
Expand Down Expand Up @@ -119,3 +120,18 @@ fn test_blskeypair_to_group() {
);
assert_eq!(*ecies_pk.as_element(), G2Element::generator() * sk);
}

#[test]
fn test_zeroization_on_drop() {
let ptr: *const u8;
{
let sk = PrivateKey::<G2Element>::new(&mut thread_rng());
ptr = std::ptr::addr_of!(sk.0) as *const u8;
}

unsafe {
for i in 0..SCALAR_LENGTH {
assert_eq!(*ptr.add(i), 0);
}
}
}
3 changes: 2 additions & 1 deletion fastcrypto-tbls/src/tests/nodes_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ use rand::thread_rng;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::num::NonZeroU16;
use zeroize::Zeroize;

fn get_nodes<G>(n: u16) -> Vec<Node<G>>
where
G: GroupElement + Serialize + DeserializeOwned,
G::ScalarType: FiatShamirChallenge,
G::ScalarType: FiatShamirChallenge + Zeroize,
{
let sk = ecies::PrivateKey::<G>::new(&mut thread_rng());
let pk = ecies::PublicKey::<G>::from_private_key(&sk);
Expand Down
7 changes: 7 additions & 0 deletions fastcrypto/src/groups/bls12381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use serde::{de, Deserialize};
use std::fmt::Debug;
use std::ops::{Add, Div, Mul, Neg, Sub};
use std::ptr;
use zeroize::Zeroize;

/// Elements of the group G_1 in BLS 12-381.
#[derive(Clone, Copy, Eq, PartialEq, GroupOpsExtend)]
Expand Down Expand Up @@ -655,6 +656,12 @@ impl GroupElement for Scalar {
}
}

impl Zeroize for Scalar {
fn zeroize(&mut self) {
self.0.l.zeroize();
}
}

impl Add for Scalar {
type Output = Scalar;

Expand Down

0 comments on commit a3d5b18

Please sign in to comment.