Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pg-curve = { version = "0.2.0", features = [
subtle = { version = "2.4.1", default-features = false }
tiny-keccak = { version = "2.0.2", features = ["sha3", "shake"] }
aes-gcm = { version = "0.10", optional = true }
zeroize = { version = "1.7", default-features = false, features = ["derive"], optional = true }

[target.wasm32-unknown-unknown.dependencies]
getrandom = { version = "0.2", features = ["js"] }
Expand All @@ -42,6 +43,7 @@ kv1 = []
waters = []
waters_naccache = []
mkem = ["aes-gcm"]
zeroize = ["dep:zeroize", "pg-curve/zeroize"]

[lib]
bench = false
Expand Down
16 changes: 16 additions & 0 deletions src/ibe/boyen_waters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,15 @@ pub struct PublicKey {
}

/// Secret key parameter generated by the PKG used to extract user secret keys.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct SecretKey {
alpha: Scalar,
t1: Scalar,
Expand All @@ -59,7 +67,15 @@ pub struct SecretKey {
}

/// Points on the paired curves that form the user secret key.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
Comment thread
dobby-coder[bot] marked this conversation as resolved.
pub struct UserSecretKey {
d: [G2Affine; 5],
}
Expand Down
16 changes: 16 additions & 0 deletions src/ibe/cgw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,15 @@ pub struct PublicKey {

/// Secret key parameter generated by the PKG used to extract user secret keys.
/// Also known as MSK.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct SecretKey {
b: [Scalar; 2],
k: [Scalar; 2],
Expand All @@ -58,7 +66,15 @@ pub struct SecretKey {

/// User secret key. Can be used to decrypt the corresponding ciphertext.
/// Also known as USK_{id}.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct UserSecretKey {
d0: [G2Affine; 2],
d1: [G2Affine; 2],
Expand Down
16 changes: 16 additions & 0 deletions src/ibe/waters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,29 @@ pub struct PublicKey {
}

/// Secret key parameter generated by the PKG used to extract user secret keys.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct SecretKey {
g1prime: G1Affine,
}

/// Points on the paired curves that form the user secret key.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct UserSecretKey {
d1: G1Affine,
d2: G2Affine,
Expand Down
16 changes: 16 additions & 0 deletions src/ibe/waters_naccache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,29 @@ pub struct PublicKey {
pub struct Identity([Scalar; CHUNKS]);

/// Secret key parameter generated by the PKG used to extract user secret keys.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct SecretKey {
g2prime: G2Affine,
}

/// Points on the paired curves that form the user secret key.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct UserSecretKey {
d1: G2Affine,
d2: G1Affine,
Expand Down
8 changes: 8 additions & 0 deletions src/kem/cgw_fo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@ pub const USK_BYTES: usize = CPA_USK_BYTES + ID_BYTES;

/// User secret key. Can be used to decaps the corresponding ciphertext.
/// Also known as USK_{id}.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct UserSecretKey {
usk: crate::ibe::cgw::UserSecretKey,
id: Identity,
Expand Down
49 changes: 49 additions & 0 deletions src/kem/cgw_kv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ pub struct PublicKey {

/// Secret key parameter generated by the PKG used to extract user secret keys.
/// Also known as MSK.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct SecretKey {
b: [Scalar; 2],
k: [Scalar; 2],
Expand All @@ -58,7 +66,15 @@ pub struct SecretKey {

/// User secret key. Can be used to decaps the corresponding ciphertext.
/// Also known as USK_{id}.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct UserSecretKey {
d0: [G2Affine; 2],
d1: [G2Affine; 2],
Expand Down Expand Up @@ -516,4 +532,37 @@ mod tests {

#[cfg(feature = "mkem")]
test_multi_kem!(CGWKV);

#[cfg(feature = "zeroize")]
#[test]
fn secret_types_zeroize() {
use zeroize::Zeroize;
let mut rng = rand::thread_rng();
let id = <CGWKV as IBKEM>::Id::derive_str("alice@example.com");
let (pk, mut sk) = CGWKV::setup(&mut rng);
let mut usk = CGWKV::extract_usk(Some(&pk), &sk, &id, &mut rng);
let (_ct, mut ss) = CGWKV::encaps(&pk, &id, &mut rng);

// Snapshot serialized form so we can assert zeroization actually blanks it.
let sk_bytes_before = sk.to_bytes();
let usk_bytes_before = usk.to_bytes();
let ss_bytes_before = ss.0;

sk.zeroize();
usk.zeroize();
ss.zeroize();

assert_ne!(sk.to_bytes(), sk_bytes_before, "SecretKey did not zeroize");
assert_ne!(
usk.to_bytes(),
usk_bytes_before,
"UserSecretKey did not zeroize"
);
assert_ne!(ss.0, ss_bytes_before, "SharedSecret did not zeroize");
assert_eq!(
ss.0,
[0u8; crate::kem::SS_BYTES],
"SharedSecret bytes should be zero"
);
}
}
16 changes: 16 additions & 0 deletions src/kem/kiltz_vahlis_one.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,29 @@ pub struct PublicKey {
}

/// Secret key parameter generated by the PKG used to extract user secret keys.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct SecretKey {
alpha: G1Affine,
}

/// Points on the paired curves that form the user secret key.
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct UserSecretKey {
d1: G1Affine,
d2: G2Affine,
Expand Down
8 changes: 8 additions & 0 deletions src/kem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ pub const SS_BYTES: usize = 32;
///
/// This shared secret has roughly a 127 bits of security.
/// This is due to the fact that BLS12-381 targets this security level (optimistically).
///
/// # Zeroization
///
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
/// you **MUST** call `.zeroize()` explicitly once done. See the
/// [crate-level docs](crate#zeroizing-secret-material).
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct SharedSecret(pub [u8; SS_BYTES]);

/// Uses SHAKE256 to derive a 32-byte shared secret from a target group element.
Expand Down
37 changes: 37 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,43 @@
//!
//! assert_eq!(k, k2);
//! ```
//!
//! # Zeroizing secret material
//!
//! When the `zeroize` feature is enabled, the secret types in this crate — the
//! [`SharedSecret`](crate::kem::SharedSecret) produced by the KEMs, and the
//! `SecretKey` and `UserSecretKey` of every scheme — derive
//! [`Zeroize`](https://docs.rs/zeroize), but **not** `ZeroizeOnDrop`.
//!
//! These types are `Copy`, and a `Copy` type cannot implement `Drop` (Rust
//! forbids `Copy` and `Drop` on the same type), so `ZeroizeOnDrop` cannot be
//! derived for them. As a consequence **secret key material is not wiped from
//! memory automatically when a value goes out of scope**. If you care about
//! clearing secrets, you **MUST** call `.zeroize()` explicitly once you are
//! done with each secret value:
//!
//! ```ignore
//! use ibe::kem::{IBKEM, cgw_kv::CGWKV};
//! use ibe::Derive;
//! use zeroize::Zeroize;
//!
//! let mut rng = rand::thread_rng();
//! let id = <CGWKV as IBKEM>::Id::derive_str("alice@example.com");
//! let (pk, mut sk) = CGWKV::setup(&mut rng);
//! let mut usk = CGWKV::extract_usk(Some(&pk), &sk, &id, &mut rng);
//! let (_ct, mut ss) = CGWKV::encaps(&pk, &id, &mut rng);
//!
//! // ... use sk / usk / ss ...
//!
//! // Wipe the secret material once you are done with it.
//! sk.zeroize();
//! usk.zeroize();
//! ss.zeroize();
//! ```
//!
//! Making these types `!Copy` so that `ZeroizeOnDrop` can be derived (and the
//! wiping happens automatically) is a breaking API change; it is deferred to a
//! future major release.

#![no_std]
#![deny(missing_debug_implementations, rust_2018_idioms, missing_docs)]
Expand Down
1 change: 1 addition & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub fn rpc<Gr: UncompressedEncoding>(k: &[u8; 32], gs: &[Gr]) -> Scalar {
///
/// This identity is obtained by hashing using sha3_512.
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
pub struct Identity(pub [u8; ID_BYTES]);

impl Default for Identity {
Expand Down
Loading