Merge pull request #25 from garious/verify-historian-input

Verify event signatures before adding log entries
This commit is contained in:
Greg Fitzgerald 2018-02-28 10:34:10 -07:00 committed by GitHub
commit f3dd47948a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 7 deletions

View File

@ -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<T> {
@ -61,7 +61,9 @@ fn log_events<T: Serialize + Clone>(
}
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<Entry<Sha256Hash>> = hist.receiver.iter().collect();
assert_eq!(entries.len(), 0);
}
}

View File

@ -187,11 +187,9 @@ pub fn next_tick<T: Serialize>(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<T: Serialize>(entry: &Entry<T>, start_hash: &Sha256Hash) -> bool {
pub fn verify_event<T: Serialize>(event: &Event<T>) -> 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<T: Serialize>(entry: &Entry<T>, 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<T: Serialize>(entry: &Entry<T>, 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<T: Serialize>(entry: &Entry<T>, start_hash: &Sha256Hash) -> bool {
if !verify_event(&entry.event) {
return false;
}
entry.end_hash == next_hash(start_hash, entry.num_hashes, &entry.event)
}