Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Verify event signatures before adding log entries #25

Merged
merged 1 commit into from
Feb 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/historian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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(());
Expand Down Expand Up @@ -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 changes: 12 additions & 5 deletions src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -202,14 +200,23 @@ 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);
if !verify_signature(&from, &sign_data, &sig) {
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)
}

Expand Down