From de4e98ae07aa6dfcc3c692b044d8b0a1bd3d2e29 Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 3 May 2024 23:27:13 -0400 Subject: [PATCH] keyfork-derive-util: black-box checking all zeroes --- .../src/extended_key/private_key.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs b/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs index f13969d..5fa3b65 100644 --- a/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs +++ b/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs @@ -179,14 +179,17 @@ where .into_bytes(); let (private_key, chain_code) = hash.split_at(KEY_SIZE / 8); - // NOTE: Could potentially cause side-channel attacks, but Rust will likely optimize any - // possible comparison I could make anyways. This is kept as-is for clarity's sake, but can - // potentially leak information about the first few bytes of a key, such as if they all - // happen to be zero. - assert!( - !private_key.iter().all(|byte| *byte == 0), - bug!("hmac function returned all-zero master key") - ); + // Verify the master key is nonzero, hopefully avoiding side-channel attacks. + let mut has_any_nonzero = false; + // deoptimize arithmetic smartness + for byte in private_key.iter().map(std::hint::black_box) { + if *byte != 0 { + // deoptimize break + has_any_nonzero = std::hint::black_box(true); + } + } + + assert!(has_any_nonzero, bug!("hmac function returned all-zero master key")); Self::from_parts( private_key