Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

Commit

Permalink
Allow initializing a SHA256 engine with a state
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasnick authored and stevenroose committed May 14, 2019
1 parent 29053f6 commit bd2eb0b
Showing 1 changed file with 61 additions and 0 deletions.
61 changes: 61 additions & 0 deletions src/sha256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,18 @@ macro_rules! round(
);

impl HashEngine {
/// Create a new [HashEngine] from a midstate.
pub fn from_midstate(midstate: Midstate, length: usize) -> HashEngine {
let mut ret = [0; 8];
BigEndian::read_u32_into(&midstate[..], &mut ret);

HashEngine {
buffer: [0; BLOCK_SIZE],
h: ret,
length: length,
}
}

// Algorithm copied from libsecp256k1
fn process_block(&mut self) {
debug_assert_eq!(self.buffer.len(), BLOCK_SIZE);
Expand Down Expand Up @@ -399,6 +411,55 @@ mod tests {
);
}

#[test]
fn engine_with_state() {
let mut engine = sha256::Hash::engine();
let midstate_engine = sha256::HashEngine::from_midstate(engine.midstate(), 0);
// Fresh engine and engine initialized with fresh state should have same state
assert_eq!(engine.h, midstate_engine.h);

// Midstate changes after writing 64 bytes
engine.input(&[1; 63]);
assert_eq!(engine.h, midstate_engine.h);
engine.input(&[2; 1]);
assert_ne!(engine.h, midstate_engine.h);

// Initializing an engine with midstate from another engine should result in
// both engines producing the same hashes
let data_vec = vec![vec![3; 1], vec![4; 63], vec![5; 65], vec![6; 66]];
for data in data_vec {
let mut engine = engine.clone();
let mut midstate_engine =
sha256::HashEngine::from_midstate(engine.midstate(), engine.length);
assert_eq!(engine.h, midstate_engine.h);
assert_eq!(engine.length, midstate_engine.length);
engine.input(&data);
midstate_engine.input(&data);
assert_eq!(engine.h, midstate_engine.h);
let hash1 = sha256::Hash::from_engine(engine);
let hash2 = sha256::Hash::from_engine(midstate_engine);
assert_eq!(hash1, hash2);
}

// Test that a specific midstate results in a specific hash. Midstate was
// obtained by applying sha256 to sha256("MuSig coefficient")||sha256("MuSig
// coefficient").
static MIDSTATE: [u8; 32] = [
0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0x97, 0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30,
0xd8, 0x64, 0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f, 0x6f, 0x43, 0xb8, 0x01,
0x85, 0xce, 0x27, 0xcd,
];
static HASH_EXPECTED: [u8; 32] = [
0x18, 0x84, 0xe4, 0x72, 0x40, 0x4e, 0xf4, 0x5a, 0xb4, 0x9c, 0x4e, 0xa4, 0x9a, 0xe6,
0x23, 0xa8, 0x88, 0x52, 0x7f, 0x7d, 0x8a, 0x06, 0x94, 0x20, 0x8f, 0xf1, 0xf7, 0xa9,
0xd5, 0x69, 0x09, 0x59,
];
let midstate_engine =
sha256::HashEngine::from_midstate(sha256::Midstate::from_inner(MIDSTATE), 64);
let hash = sha256::Hash::from_engine(midstate_engine);
assert_eq!(hash, sha256::Hash(HASH_EXPECTED));
}

#[cfg(feature="serde")]
#[test]
fn sha256_serde() {
Expand Down

0 comments on commit bd2eb0b

Please sign in to comment.