Merge pull request #25 from garious/verify-historian-input
Verify event signatures before adding log entries
This commit is contained in:
commit
f3dd47948a
|
@ -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,8 +61,10 @@ fn log_events<T: Serialize + Clone>(
|
|||
}
|
||||
match receiver.try_recv() {
|
||||
Ok(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);
|
||||
}
|
||||
}
|
||||
|
|
17
src/log.rs
17
src/log.rs
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue