Skip to content

Commit a269b06

Browse files
committed
Implement Zeroize
Introduce new dependency `zeroize`. Implement `Zeroize` for our array types with the `impl_array_newtype` macro. Add a unit test that test a newly create `SecretKey` is zeroized after calling `zeroize()` on it.
1 parent 8e61874 commit a269b06

File tree

5 files changed

+40
-1
lines changed

5 files changed

+40
-1
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ secp256k1-sys = { version = "0.4.0", default-features = false, path = "./secp256
3030
bitcoin_hashes = { version = "0.9", optional = true }
3131
rand = { version = "0.6", default-features = false, optional = true }
3232
serde = { version = "1.0", default-features = false, optional = true }
33-
33+
zeroize = { version = "1.2", default-features = false, optional = true }
3434

3535
[dev-dependencies]
3636
rand = "0.6"

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ before_script:
3636
fi
3737
```
3838
39+
## Zeroize
40+
41+
Zeroizing secrets is supported using the `zeroize` feature. Enabling this
42+
feature changes the MSRV to 1.44 (see https://docs.rs/zeroize/1.2.0/zeroize/).
43+
44+
The aim of the `zeroize` feature is to allow users of this library to reduce the
45+
number of copies of secrets in memory (by wrapping our types, implementing
46+
`Zeroize` and implementing `Drop` (i.e. derive `Zeroize`). Our aim is not to
47+
guarantee that there are no copies left un-zeroed in memory. Internally we
48+
absolutely do leave secrets on the stack.
49+
50+
> I think even zeroing some out the copies is better than none, because every
51+
> copy makes a Heartbleed-like attack a little easier.
52+
3953
## Fuzzing
4054

4155
If you want to fuzz this library, or any library which depends on it, you will

secp256k1-sys/src/macros.rs

+8
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ macro_rules! impl_array_newtype {
8383
}
8484
}
8585

86+
#[cfg(feature = "zeroize")]
87+
impl zeroize::Zeroize for $thing {
88+
fn zeroize(&mut self) {
89+
let &mut $thing(ref mut dat) = self;
90+
dat.zeroize()
91+
}
92+
}
93+
8694
impl ::core::ops::Index<usize> for $thing {
8795
type Output = $ty;
8896

src/key.rs

+16
Original file line numberDiff line numberDiff line change
@@ -850,4 +850,20 @@ mod test {
850850
assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]);
851851
assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]);
852852
}
853+
854+
#[cfg(feature = "zeroize")]
855+
#[test]
856+
fn zeroize_secret_key() {
857+
use zeroize::Zeroize;
858+
859+
let mut sk = SecretKey::new(&mut thread_rng());
860+
sk.zeroize();
861+
862+
let ptr = &sk.0[0];
863+
864+
for _ in 0..32 {
865+
assert_eq!(*ptr, 0x00);
866+
}
867+
}
853868
}
869+

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ pub use secp256k1_sys as ffi;
135135
#[cfg(any(test, feature = "rand"))] use rand::Rng;
136136
#[cfg(any(test, feature = "std"))] extern crate core;
137137
#[cfg(all(test, target_arch = "wasm32"))] extern crate wasm_bindgen_test;
138+
#[cfg(feature = "zeroize")] extern crate zeroize;
138139

139140
use core::{fmt, ptr, str};
140141

0 commit comments

Comments
 (0)