Skip to content

Commit 7b7266d

Browse files
docs: document mandatory .zeroize() call for secret types (#49)
The zeroize feature (#14) derives Zeroize but not ZeroizeOnDrop, because the secret types are Copy. Secret material is therefore not wiped on drop and callers MUST call .zeroize() explicitly. Document this contract in the crate-level docs and add a MUST-call annotation to every SharedSecret, SecretKey and UserSecretKey across all KEM and IBE schemes. Co-authored-by: dobby-yivi-agent[bot] <275734547+dobby-yivi-agent[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b5e7625 commit 7b7266d

9 files changed

Lines changed: 135 additions & 0 deletions

File tree

src/ibe/boyen_waters.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ pub struct PublicKey {
4949
}
5050

5151
/// Secret key parameter generated by the PKG used to extract user secret keys.
52+
///
53+
/// # Zeroization
54+
///
55+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
56+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
57+
/// you **MUST** call `.zeroize()` explicitly once done. See the
58+
/// [crate-level docs](crate#zeroizing-secret-material).
5259
#[derive(Debug, Clone, Copy, PartialEq)]
5360
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
5461
pub struct SecretKey {
@@ -60,6 +67,13 @@ pub struct SecretKey {
6067
}
6168

6269
/// Points on the paired curves that form the user secret key.
70+
///
71+
/// # Zeroization
72+
///
73+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
74+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
75+
/// you **MUST** call `.zeroize()` explicitly once done. See the
76+
/// [crate-level docs](crate#zeroizing-secret-material).
6377
#[derive(Debug, Clone, Copy, PartialEq)]
6478
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
6579
pub struct UserSecretKey {

src/ibe/cgw.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ pub struct PublicKey {
4848

4949
/// Secret key parameter generated by the PKG used to extract user secret keys.
5050
/// Also known as MSK.
51+
///
52+
/// # Zeroization
53+
///
54+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
55+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
56+
/// you **MUST** call `.zeroize()` explicitly once done. See the
57+
/// [crate-level docs](crate#zeroizing-secret-material).
5158
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
5259
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
5360
pub struct SecretKey {
@@ -59,6 +66,13 @@ pub struct SecretKey {
5966

6067
/// User secret key. Can be used to decrypt the corresponding ciphertext.
6168
/// Also known as USK_{id}.
69+
///
70+
/// # Zeroization
71+
///
72+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
73+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
74+
/// you **MUST** call `.zeroize()` explicitly once done. See the
75+
/// [crate-level docs](crate#zeroizing-secret-material).
6276
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
6377
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
6478
pub struct UserSecretKey {

src/ibe/waters.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,27 @@ pub struct PublicKey {
4848
}
4949

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

5764
/// Points on the paired curves that form the user secret key.
65+
///
66+
/// # Zeroization
67+
///
68+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
69+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
70+
/// you **MUST** call `.zeroize()` explicitly once done. See the
71+
/// [crate-level docs](crate#zeroizing-secret-material).
5872
#[derive(Debug, Clone, Copy, PartialEq)]
5973
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
6074
pub struct UserSecretKey {

src/ibe/waters_naccache.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,27 @@ pub struct PublicKey {
5858
pub struct Identity([Scalar; CHUNKS]);
5959

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

6774
/// Points on the paired curves that form the user secret key.
75+
///
76+
/// # Zeroization
77+
///
78+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
79+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
80+
/// you **MUST** call `.zeroize()` explicitly once done. See the
81+
/// [crate-level docs](crate#zeroizing-secret-material).
6882
#[derive(Clone, Copy, Debug, PartialEq)]
6983
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
7084
pub struct UserSecretKey {

src/kem/cgw_fo.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ pub const USK_BYTES: usize = CPA_USK_BYTES + ID_BYTES;
2929

3030
/// User secret key. Can be used to decaps the corresponding ciphertext.
3131
/// Also known as USK_{id}.
32+
///
33+
/// # Zeroization
34+
///
35+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
36+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
37+
/// you **MUST** call `.zeroize()` explicitly once done. See the
38+
/// [crate-level docs](crate#zeroizing-secret-material).
3239
#[derive(Debug, Clone, Copy, PartialEq)]
3340
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
3441
pub struct UserSecretKey {

src/kem/cgw_kv.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ pub struct PublicKey {
4747

4848
/// Secret key parameter generated by the PKG used to extract user secret keys.
4949
/// Also known as MSK.
50+
///
51+
/// # Zeroization
52+
///
53+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
54+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
55+
/// you **MUST** call `.zeroize()` explicitly once done. See the
56+
/// [crate-level docs](crate#zeroizing-secret-material).
5057
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
5158
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
5259
pub struct SecretKey {
@@ -59,6 +66,13 @@ pub struct SecretKey {
5966

6067
/// User secret key. Can be used to decaps the corresponding ciphertext.
6168
/// Also known as USK_{id}.
69+
///
70+
/// # Zeroization
71+
///
72+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
73+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
74+
/// you **MUST** call `.zeroize()` explicitly once done. See the
75+
/// [crate-level docs](crate#zeroizing-secret-material).
6276
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
6377
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
6478
pub struct UserSecretKey {

src/kem/kiltz_vahlis_one.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,27 @@ pub struct PublicKey {
4444
}
4545

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

5360
/// Points on the paired curves that form the user secret key.
61+
///
62+
/// # Zeroization
63+
///
64+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
65+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
66+
/// you **MUST** call `.zeroize()` explicitly once done. See the
67+
/// [crate-level docs](crate#zeroizing-secret-material).
5468
#[derive(Debug, Clone, Copy, PartialEq)]
5569
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
5670
pub struct UserSecretKey {

src/kem/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ pub const SS_BYTES: usize = 32;
3434
///
3535
/// This shared secret has roughly a 127 bits of security.
3636
/// This is due to the fact that BLS12-381 targets this security level (optimistically).
37+
///
38+
/// # Zeroization
39+
///
40+
/// With the `zeroize` feature enabled this type derives `Zeroize` but **not**
41+
/// `ZeroizeOnDrop` (it is `Copy`). Secret material is **not** cleared on drop —
42+
/// you **MUST** call `.zeroize()` explicitly once done. See the
43+
/// [crate-level docs](crate#zeroizing-secret-material).
3744
#[derive(Clone, Copy, Debug, PartialEq)]
3845
#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
3946
pub struct SharedSecret(pub [u8; SS_BYTES]);

src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,43 @@
4040
//!
4141
//! assert_eq!(k, k2);
4242
//! ```
43+
//!
44+
//! # Zeroizing secret material
45+
//!
46+
//! When the `zeroize` feature is enabled, the secret types in this crate — the
47+
//! [`SharedSecret`](crate::kem::SharedSecret) produced by the KEMs, and the
48+
//! `SecretKey` and `UserSecretKey` of every scheme — derive
49+
//! [`Zeroize`](https://docs.rs/zeroize), but **not** `ZeroizeOnDrop`.
50+
//!
51+
//! These types are `Copy`, and a `Copy` type cannot implement `Drop` (Rust
52+
//! forbids `Copy` and `Drop` on the same type), so `ZeroizeOnDrop` cannot be
53+
//! derived for them. As a consequence **secret key material is not wiped from
54+
//! memory automatically when a value goes out of scope**. If you care about
55+
//! clearing secrets, you **MUST** call `.zeroize()` explicitly once you are
56+
//! done with each secret value:
57+
//!
58+
//! ```ignore
59+
//! use ibe::kem::{IBKEM, cgw_kv::CGWKV};
60+
//! use ibe::Derive;
61+
//! use zeroize::Zeroize;
62+
//!
63+
//! let mut rng = rand::thread_rng();
64+
//! let id = <CGWKV as IBKEM>::Id::derive_str("alice@example.com");
65+
//! let (pk, mut sk) = CGWKV::setup(&mut rng);
66+
//! let mut usk = CGWKV::extract_usk(Some(&pk), &sk, &id, &mut rng);
67+
//! let (_ct, mut ss) = CGWKV::encaps(&pk, &id, &mut rng);
68+
//!
69+
//! // ... use sk / usk / ss ...
70+
//!
71+
//! // Wipe the secret material once you are done with it.
72+
//! sk.zeroize();
73+
//! usk.zeroize();
74+
//! ss.zeroize();
75+
//! ```
76+
//!
77+
//! Making these types `!Copy` so that `ZeroizeOnDrop` can be derived (and the
78+
//! wiping happens automatically) is a breaking API change; it is deferred to a
79+
//! future major release.
4380
4481
#![no_std]
4582
#![deny(missing_debug_implementations, rust_2018_idioms, missing_docs)]

0 commit comments

Comments
 (0)