From c3bb20748848a7e0650a13c4217eacfe946a1772 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 28 Feb 2018 10:23:01 -0700 Subject: [PATCH] Verify event signatures before adding log entries --- src/historian.rs | 26 ++++++++++++++++++++++++-- src/log.rs | 17 ++++++++++++----- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/historian.rs b/src/historian.rs index 2612c3205..0daba33fb 100644 --- a/src/historian.rs +++ b/src/historian.rs @@ -8,7 +8,7 @@ use std::thread::JoinHandle; use std::sync::mpsc::{Receiver, Sender}; use std::time::{Duration, SystemTime}; -use log::{hash, hash_event, Entry, Event, Sha256Hash}; +use log::{hash, hash_event, verify_event, Entry, Event, Sha256Hash}; use serde::Serialize; pub struct Historian { @@ -61,7 +61,9 @@ fn log_events( } match receiver.try_recv() { Ok(event) => { - log_event(sender, num_hashes, end_hash, event)?; + if verify_event(&event) { + log_event(sender, num_hashes, end_hash, event)?; + } } Err(TryRecvError::Empty) => { return Ok(()); @@ -184,4 +186,24 @@ mod tests { assert!(entries.len() > 1); assert!(verify_slice(&entries, &zero)); } + + #[test] + fn test_bad_event_attack() { + let zero = Sha256Hash::default(); + let hist = Historian::new(&zero, None); + let keypair = generate_keypair(); + let mut event0 = sign_hash(hash(b"hello, world"), &keypair); + if let Event::Claim { key, sig, .. } = event0 { + let data = hash(b"goodbye cruel world"); + event0 = Event::Claim { key, data, sig }; + } + hist.sender.send(event0).unwrap(); + drop(hist.sender); + assert_eq!( + hist.thread_hdl.join().unwrap().1, + ExitReason::RecvDisconnected + ); + let entries: Vec> = hist.receiver.iter().collect(); + assert_eq!(entries.len(), 0); + } } diff --git a/src/log.rs b/src/log.rs index 47ac70ec3..00df286cc 100644 --- a/src/log.rs +++ b/src/log.rs @@ -187,11 +187,9 @@ pub fn next_tick(start_hash: &Sha256Hash, num_hashes: u64) -> Entr next_entry(start_hash, num_hashes, Event::Tick) } -/// Verifies self.end_hash is the result of hashing a 'start_hash' 'self.num_hashes' times. -/// If the event is not a Tick, then hash that as well. -pub fn verify_entry(entry: &Entry, start_hash: &Sha256Hash) -> bool { +pub fn verify_event(event: &Event) -> bool { use bincode::serialize; - if let Event::Claim { key, ref data, sig } = entry.event { + if let Event::Claim { key, ref data, sig } = *event { let mut claim_data = serialize(&data).unwrap(); if !verify_signature(&key, &claim_data, &sig) { return false; @@ -202,7 +200,7 @@ pub fn verify_entry(entry: &Entry, start_hash: &Sha256Hash) -> to, ref data, sig, - } = entry.event + } = *event { let mut sign_data = serialize(&data).unwrap(); sign_data.extend_from_slice(&to); @@ -210,6 +208,15 @@ pub fn verify_entry(entry: &Entry, start_hash: &Sha256Hash) -> return false; } } + true +} + +/// Verifies self.end_hash is the result of hashing a 'start_hash' 'self.num_hashes' times. +/// If the event is not a Tick, then hash that as well. +pub fn verify_entry(entry: &Entry, start_hash: &Sha256Hash) -> bool { + if !verify_event(&entry.event) { + return false; + } entry.end_hash == next_hash(start_hash, entry.num_hashes, &entry.event) }