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

Commit bd2eb0b

Browse files
jonasnickstevenroose
authored andcommitted
Allow initializing a SHA256 engine with a state
1 parent 29053f6 commit bd2eb0b

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

src/sha256.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,18 @@ macro_rules! round(
209209
);
210210

211211
impl HashEngine {
212+
/// Create a new [HashEngine] from a midstate.
213+
pub fn from_midstate(midstate: Midstate, length: usize) -> HashEngine {
214+
let mut ret = [0; 8];
215+
BigEndian::read_u32_into(&midstate[..], &mut ret);
216+
217+
HashEngine {
218+
buffer: [0; BLOCK_SIZE],
219+
h: ret,
220+
length: length,
221+
}
222+
}
223+
212224
// Algorithm copied from libsecp256k1
213225
fn process_block(&mut self) {
214226
debug_assert_eq!(self.buffer.len(), BLOCK_SIZE);
@@ -399,6 +411,55 @@ mod tests {
399411
);
400412
}
401413

414+
#[test]
415+
fn engine_with_state() {
416+
let mut engine = sha256::Hash::engine();
417+
let midstate_engine = sha256::HashEngine::from_midstate(engine.midstate(), 0);
418+
// Fresh engine and engine initialized with fresh state should have same state
419+
assert_eq!(engine.h, midstate_engine.h);
420+
421+
// Midstate changes after writing 64 bytes
422+
engine.input(&[1; 63]);
423+
assert_eq!(engine.h, midstate_engine.h);
424+
engine.input(&[2; 1]);
425+
assert_ne!(engine.h, midstate_engine.h);
426+
427+
// Initializing an engine with midstate from another engine should result in
428+
// both engines producing the same hashes
429+
let data_vec = vec![vec![3; 1], vec![4; 63], vec![5; 65], vec![6; 66]];
430+
for data in data_vec {
431+
let mut engine = engine.clone();
432+
let mut midstate_engine =
433+
sha256::HashEngine::from_midstate(engine.midstate(), engine.length);
434+
assert_eq!(engine.h, midstate_engine.h);
435+
assert_eq!(engine.length, midstate_engine.length);
436+
engine.input(&data);
437+
midstate_engine.input(&data);
438+
assert_eq!(engine.h, midstate_engine.h);
439+
let hash1 = sha256::Hash::from_engine(engine);
440+
let hash2 = sha256::Hash::from_engine(midstate_engine);
441+
assert_eq!(hash1, hash2);
442+
}
443+
444+
// Test that a specific midstate results in a specific hash. Midstate was
445+
// obtained by applying sha256 to sha256("MuSig coefficient")||sha256("MuSig
446+
// coefficient").
447+
static MIDSTATE: [u8; 32] = [
448+
0x0f, 0xd0, 0x69, 0x0c, 0xfe, 0xfe, 0xae, 0x97, 0x99, 0x6e, 0xac, 0x7f, 0x5c, 0x30,
449+
0xd8, 0x64, 0x8c, 0x4a, 0x05, 0x73, 0xac, 0xa1, 0xa2, 0x2f, 0x6f, 0x43, 0xb8, 0x01,
450+
0x85, 0xce, 0x27, 0xcd,
451+
];
452+
static HASH_EXPECTED: [u8; 32] = [
453+
0x18, 0x84, 0xe4, 0x72, 0x40, 0x4e, 0xf4, 0x5a, 0xb4, 0x9c, 0x4e, 0xa4, 0x9a, 0xe6,
454+
0x23, 0xa8, 0x88, 0x52, 0x7f, 0x7d, 0x8a, 0x06, 0x94, 0x20, 0x8f, 0xf1, 0xf7, 0xa9,
455+
0xd5, 0x69, 0x09, 0x59,
456+
];
457+
let midstate_engine =
458+
sha256::HashEngine::from_midstate(sha256::Midstate::from_inner(MIDSTATE), 64);
459+
let hash = sha256::Hash::from_engine(midstate_engine);
460+
assert_eq!(hash, sha256::Hash(HASH_EXPECTED));
461+
}
462+
402463
#[cfg(feature="serde")]
403464
#[test]
404465
fn sha256_serde() {

0 commit comments

Comments
 (0)