Fill BlindingFactor with zeros on Drop (#2847)

* Implement simple zeroing of BlindingFactor in Drop

* rustfmt

* Make Debug implementation for BlindingFactor empty

* Implement BlindingFactor zeroing unit test

* mnemonic.rs: fix deprecated warning in test_bip39_random test

* Use zeroize crate to clear BlindingFactor

* Fix comment and implement dummy Debug trait for BlindingFactor

* Fix formatter
This commit is contained in:
eupn
2019-05-31 04:16:53 +07:00
committed by hashmap
parent 25a2ee1233
commit 56b62a319b
8 changed files with 68 additions and 10 deletions
+2 -1
View File
@@ -324,10 +324,11 @@ mod tests {
#[test]
fn test_bip39_random() {
use rand::seq::SliceRandom;
let sizes: [usize; 5] = [16, 20, 24, 28, 32];
let mut rng = thread_rng();
let size = *rng.choose(&sizes).unwrap();
let size = *sizes.choose(&mut rng).unwrap();
let mut entropy: Vec<u8> = Vec::with_capacity(size);
for _ in 0..size {
+34 -2
View File
@@ -32,6 +32,7 @@ use crate::util::secp::key::{PublicKey, SecretKey};
use crate::util::secp::pedersen::Commitment;
use crate::util::secp::{self, Message, Secp256k1, Signature};
use crate::util::static_secp_instance;
use zeroize::Zeroize;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
@@ -227,12 +228,13 @@ impl fmt::Display for Identifier {
}
}
#[derive(Clone, Copy, PartialEq, Serialize, Deserialize)]
#[derive(Default, Clone, PartialEq, Serialize, Deserialize, Zeroize)]
pub struct BlindingFactor([u8; SECRET_KEY_SIZE]);
// Dummy `Debug` implementation that prevents secret leakage.
impl fmt::Debug for BlindingFactor {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.to_hex())
write!(f, "BlindingFactor(<secret key hidden>)")
}
}
@@ -480,8 +482,38 @@ mod test {
use rand::thread_rng;
use crate::types::{BlindingFactor, ExtKeychainPath, Identifier};
use crate::util::secp::constants::SECRET_KEY_SIZE;
use crate::util::secp::key::{SecretKey, ZERO_KEY};
use crate::util::secp::Secp256k1;
use std::slice::from_raw_parts;
// This tests cleaning of BlindingFactor (e.g. secret key) on Drop.
// To make this test fail, just remove `Zeroize` derive from `BlindingFactor` definition.
#[test]
fn blinding_factor_clear_on_drop() {
// Create buffer for blinding factor filled with non-zero bytes.
let bf_bytes = [0xAA; SECRET_KEY_SIZE];
let ptr = {
// Fill blinding factor with some "sensitive" data
let bf = BlindingFactor::from_slice(&bf_bytes[..]);
bf.0.as_ptr()
// -- after this line BlindingFactor should be zeroed
};
// Unsafely get data from where BlindingFactor was in memory. Should be all zeros.
let bf_bytes = unsafe { from_raw_parts(ptr, SECRET_KEY_SIZE) };
// There should be all zeroes.
let mut all_zeros = true;
for b in bf_bytes {
if *b != 0x00 {
all_zeros = false;
}
}
assert!(all_zeros)
}
#[test]
fn split_blinding_factor() {