From 491ba9da84975c03146bdd694353634d47cdb2b4 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Wed, 7 Mar 2018 15:32:22 -0700 Subject: [PATCH] Add accessors to keypairs and signatures --- src/accountant.rs | 22 +++++++++----------- src/accountant_stub.rs | 6 +++--- src/bin/client-demo.rs | 8 ++++---- src/bin/demo.rs | 6 +++--- src/bin/genesis-file-demo.rs | 10 ++++----- src/genesis.rs | 24 ++++++++-------------- src/log.rs | 8 ++++---- src/signature.rs | 40 +++++++++++++++++++++++------------- src/transaction.rs | 31 ++++++++++++++-------------- 9 files changed, 79 insertions(+), 76 deletions(-) diff --git a/src/accountant.rs b/src/accountant.rs index 72bf12b8c..b1cb6b232 100644 --- a/src/accountant.rs +++ b/src/accountant.rs @@ -146,19 +146,18 @@ impl Accountant { #[cfg(test)] mod tests { use super::*; - use signature::{generate_keypair, get_pubkey}; + use signature::KeyPairUtil; use logger::ExitReason; #[test] fn test_accountant() { let alice = Genesis::new(10_000); - let bob_pubkey = get_pubkey(&generate_keypair()); + let bob_pubkey = KeyPair::new().pubkey(); let mut acc = Accountant::new(&alice, Some(2)); - acc.transfer(1_000, &alice.get_keypair(), bob_pubkey) - .unwrap(); + acc.transfer(1_000, &alice.keypair(), bob_pubkey).unwrap(); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_000); - acc.transfer(500, &alice.get_keypair(), bob_pubkey).unwrap(); + acc.transfer(500, &alice.keypair(), bob_pubkey).unwrap(); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_500); drop(acc.historian.sender); @@ -172,15 +171,14 @@ mod tests { fn test_invalid_transfer() { let alice = Genesis::new(11_000); let mut acc = Accountant::new(&alice, Some(2)); - let bob_pubkey = get_pubkey(&generate_keypair()); - acc.transfer(1_000, &alice.get_keypair(), bob_pubkey) - .unwrap(); + let bob_pubkey = KeyPair::new().pubkey(); + acc.transfer(1_000, &alice.keypair(), bob_pubkey).unwrap(); assert_eq!( - acc.transfer(10_001, &alice.get_keypair(), bob_pubkey), + acc.transfer(10_001, &alice.keypair(), bob_pubkey), Err(AccountingError::InsufficientFunds) ); - let alice_pubkey = get_pubkey(&alice.get_keypair()); + let alice_pubkey = alice.keypair().pubkey(); assert_eq!(acc.get_balance(&alice_pubkey).unwrap(), 10_000); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 1_000); @@ -195,8 +193,8 @@ mod tests { fn test_transfer_to_newb() { let alice = Genesis::new(10_000); let mut acc = Accountant::new(&alice, Some(2)); - let alice_keypair = alice.get_keypair(); - let bob_pubkey = get_pubkey(&generate_keypair()); + let alice_keypair = alice.keypair(); + let bob_pubkey = KeyPair::new().pubkey(); acc.transfer(500, &alice_keypair, bob_pubkey).unwrap(); assert_eq!(acc.get_balance(&bob_pubkey).unwrap(), 500); diff --git a/src/accountant_stub.rs b/src/accountant_stub.rs index f3097022a..b55ddb46c 100644 --- a/src/accountant_stub.rs +++ b/src/accountant_stub.rs @@ -116,7 +116,7 @@ mod tests { use std::thread::{sleep, spawn}; use std::time::Duration; use genesis::Genesis; - use signature::{generate_keypair, get_pubkey}; + use signature::{KeyPair, KeyPairUtil}; #[test] fn test_accountant_stub() { @@ -124,14 +124,14 @@ mod tests { let send_addr = "127.0.0.1:9001"; let alice = Genesis::new(10_000); let acc = Accountant::new(&alice, None); - let bob_pubkey = get_pubkey(&generate_keypair()); + let bob_pubkey = KeyPair::new().pubkey(); spawn(move || AccountantSkel::new(acc).serve(addr).unwrap()); sleep(Duration::from_millis(30)); let socket = UdpSocket::bind(send_addr).unwrap(); let mut acc = AccountantStub::new(addr, socket); let last_id = acc.get_last_id().unwrap(); - let sig = acc.transfer(500, &alice.get_keypair(), bob_pubkey, &last_id) + let sig = acc.transfer(500, &alice.keypair(), bob_pubkey, &last_id) .unwrap(); acc.wait_on_signature(&sig).unwrap(); assert_eq!(acc.get_balance(&bob_pubkey).unwrap().unwrap(), 500); diff --git a/src/bin/client-demo.rs b/src/bin/client-demo.rs index 3005a1fa1..ff1f142e9 100644 --- a/src/bin/client-demo.rs +++ b/src/bin/client-demo.rs @@ -2,7 +2,7 @@ extern crate serde_json; extern crate silk; use silk::accountant_stub::AccountantStub; -use silk::signature::{generate_keypair, get_pubkey}; +use silk::signature::{KeyPair, KeyPairUtil}; use silk::transaction::Transaction; use silk::genesis::Genesis; use std::time::Instant; @@ -14,8 +14,8 @@ fn main() { let send_addr = "127.0.0.1:8001"; let gen: Genesis = serde_json::from_reader(stdin()).unwrap(); - let alice_keypair = gen.get_keypair(); - let alice_pubkey = gen.get_pubkey(); + let alice_keypair = gen.keypair(); + let alice_pubkey = gen.pubkey(); let socket = UdpSocket::bind(send_addr).unwrap(); let mut acc = AccountantStub::new(addr, socket); @@ -28,7 +28,7 @@ fn main() { let now = Instant::now(); let transactions: Vec<_> = (0..txs) .map(|_| { - let rando_pubkey = get_pubkey(&generate_keypair()); + let rando_pubkey = KeyPair::new().pubkey(); Transaction::new(&alice_keypair, rando_pubkey, 1, last_id) }) .collect(); diff --git a/src/bin/demo.rs b/src/bin/demo.rs index 59cd7e916..a421a1348 100644 --- a/src/bin/demo.rs +++ b/src/bin/demo.rs @@ -4,7 +4,7 @@ use silk::historian::Historian; use silk::hash::Hash; use silk::entry::Entry; use silk::log::verify_slice; -use silk::signature::{generate_keypair, get_pubkey}; +use silk::signature::{KeyPair, KeyPairUtil}; use silk::transaction::Transaction; use silk::event::Event; use std::thread::sleep; @@ -13,8 +13,8 @@ use std::sync::mpsc::SendError; fn create_log(hist: &Historian, seed: &Hash) -> Result<(), SendError> { sleep(Duration::from_millis(15)); - let keypair = generate_keypair(); - let tr = Transaction::new(&keypair, get_pubkey(&keypair), 42, *seed); + let keypair = KeyPair::new(); + let tr = Transaction::new(&keypair, keypair.pubkey(), 42, *seed); let event0 = Event::Transaction(tr); hist.sender.send(event0)?; sleep(Duration::from_millis(10)); diff --git a/src/bin/genesis-file-demo.rs b/src/bin/genesis-file-demo.rs index c56986c48..57eb7c059 100644 --- a/src/bin/genesis-file-demo.rs +++ b/src/bin/genesis-file-demo.rs @@ -5,7 +5,7 @@ use silk::genesis::Genesis; use silk::event::Event; use silk::transaction::Transaction; use silk::log::create_entries; -use silk::signature::{generate_keypair, get_pubkey, KeyPair, PublicKey}; +use silk::signature::{KeyPair, KeyPairUtil, PublicKey}; use silk::hash::Hash; fn transfer(from: &KeyPair, (to, tokens): (PublicKey, i64), last_id: Hash) -> Event { @@ -13,12 +13,12 @@ fn transfer(from: &KeyPair, (to, tokens): (PublicKey, i64), last_id: Hash) -> Ev } fn main() { - let alice = (get_pubkey(&generate_keypair()), 200); - let bob = (get_pubkey(&generate_keypair()), 100); + let alice = (KeyPair::new().pubkey(), 200); + let bob = (KeyPair::new().pubkey(), 100); let gen = Genesis::new(500); - let from = gen.get_keypair(); - let seed = gen.get_seed(); + let from = gen.keypair(); + let seed = gen.seed(); let mut events = gen.create_events(); events.push(transfer(&from, alice, seed)); events.push(transfer(&from, bob, seed)); diff --git a/src/genesis.rs b/src/genesis.rs index 5c410b2ad..8e1f1e981 100644 --- a/src/genesis.rs +++ b/src/genesis.rs @@ -2,12 +2,11 @@ use event::Event; use transaction::Transaction; -use signature::{get_pubkey, PublicKey}; +use signature::{KeyPair, KeyPairUtil, PublicKey}; use entry::Entry; use log::create_entries; use hash::{hash, Hash}; use ring::rand::SystemRandom; -use ring::signature::Ed25519KeyPair; use untrusted::Input; #[derive(Serialize, Deserialize, Debug)] @@ -19,34 +18,29 @@ pub struct Genesis { impl Genesis { pub fn new(tokens: i64) -> Self { let rnd = SystemRandom::new(); - let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rnd).unwrap().to_vec(); + let pkcs8 = KeyPair::generate_pkcs8(&rnd).unwrap().to_vec(); Genesis { pkcs8, tokens } } - pub fn get_seed(&self) -> Hash { + pub fn seed(&self) -> Hash { hash(&self.pkcs8) } - pub fn get_keypair(&self) -> Ed25519KeyPair { - Ed25519KeyPair::from_pkcs8(Input::from(&self.pkcs8)).unwrap() + pub fn keypair(&self) -> KeyPair { + KeyPair::from_pkcs8(Input::from(&self.pkcs8)).unwrap() } - pub fn get_pubkey(&self) -> PublicKey { - get_pubkey(&self.get_keypair()) + pub fn pubkey(&self) -> PublicKey { + self.keypair().pubkey() } pub fn create_events(&self) -> Vec { - let tr = Transaction::new( - &self.get_keypair(), - self.get_pubkey(), - self.tokens, - self.get_seed(), - ); + let tr = Transaction::new(&self.keypair(), self.pubkey(), self.tokens, self.seed()); vec![Event::Tick, Event::Transaction(tr)] } pub fn create_entries(&self) -> Vec { - create_entries(&self.get_seed(), self.create_events()) + create_entries(&self.seed(), self.create_events()) } } diff --git a/src/log.rs b/src/log.rs index de3284b43..b01450cb5 100644 --- a/src/log.rs +++ b/src/log.rs @@ -48,7 +48,7 @@ pub fn next_ticks(start_hash: &Hash, num_hashes: u64, len: usize) -> Vec #[cfg(test)] mod tests { use super::*; - use signature::{generate_keypair, get_pubkey}; + use signature::{KeyPair, KeyPairUtil}; use transaction::Transaction; use hash::hash; @@ -71,9 +71,9 @@ mod tests { let zero = Hash::default(); // First, verify entries - let keypair = generate_keypair(); - let tr0 = Transaction::new(&keypair, get_pubkey(&keypair), 0, zero); - let tr1 = Transaction::new(&keypair, get_pubkey(&keypair), 1, zero); + let keypair = KeyPair::new(); + let tr0 = Transaction::new(&keypair, keypair.pubkey(), 0, zero); + let tr1 = Transaction::new(&keypair, keypair.pubkey(), 1, zero); let events = vec![Event::Transaction(tr0), Event::Transaction(tr1)]; let mut entries = create_entries(&zero, events); assert!(verify_slice(&entries, &zero)); diff --git a/src/signature.rs b/src/signature.rs index 06b705dde..9fd7b74e2 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -10,22 +10,34 @@ pub type KeyPair = Ed25519KeyPair; pub type PublicKey = GenericArray; pub type Signature = GenericArray; -/// Return a new ED25519 keypair -pub fn generate_keypair() -> KeyPair { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); - signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap() +pub trait KeyPairUtil { + fn new() -> Self; + fn pubkey(&self) -> PublicKey; } -/// Return the public key for the given keypair -pub fn get_pubkey(keypair: &KeyPair) -> PublicKey { - GenericArray::clone_from_slice(keypair.public_key_bytes()) +impl KeyPairUtil for Ed25519KeyPair { + /// Return a new ED25519 keypair + fn new() -> Self { + let rng = rand::SystemRandom::new(); + let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); + signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap() + } + + /// Return the public key for the given keypair + fn pubkey(&self) -> PublicKey { + GenericArray::clone_from_slice(self.public_key_bytes()) + } } -/// Verify a signed message with the given public key. -pub fn verify_signature(peer_public_key_bytes: &[u8], msg_bytes: &[u8], sig_bytes: &[u8]) -> bool { - let peer_public_key = untrusted::Input::from(peer_public_key_bytes); - let msg = untrusted::Input::from(msg_bytes); - let sig = untrusted::Input::from(sig_bytes); - signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok() +pub trait SignatureUtil { + fn verify(&self, peer_public_key_bytes: &[u8], msg_bytes: &[u8]) -> bool; +} + +impl SignatureUtil for GenericArray { + fn verify(&self, peer_public_key_bytes: &[u8], msg_bytes: &[u8]) -> bool { + let peer_public_key = untrusted::Input::from(peer_public_key_bytes); + let msg = untrusted::Input::from(msg_bytes); + let sig = untrusted::Input::from(self); + signature::verify(&signature::ED25519, peer_public_key, msg, sig).is_ok() + } } diff --git a/src/transaction.rs b/src/transaction.rs index ff2bc5f8d..dc3d40006 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,6 +1,6 @@ //! The `transaction` crate provides functionality for creating log transactions. -use signature::{get_pubkey, verify_signature, KeyPair, PublicKey, Signature}; +use signature::{KeyPair, KeyPairUtil, PublicKey, Signature, SignatureUtil}; use serde::Serialize; use bincode::serialize; use hash::Hash; @@ -17,7 +17,7 @@ pub struct Transaction { impl Transaction { pub fn new(from_keypair: &KeyPair, to: PublicKey, asset: T, last_id: Hash) -> Self { let mut tr = Transaction { - from: get_pubkey(&from_keypair), + from: from_keypair.pubkey(), to, asset, last_id, @@ -37,7 +37,7 @@ impl Transaction { } pub fn verify(&self) -> bool { - verify_signature(&self.from, &self.get_sign_data(), &self.sig) + self.sig.verify(&self.from, &self.get_sign_data()) } } @@ -45,24 +45,23 @@ impl Transaction { mod tests { use super::*; use bincode::{deserialize, serialize}; - use signature::*; use hash::hash; #[test] fn test_claim() { - let keypair = generate_keypair(); + let keypair = KeyPair::new(); let asset = hash(b"hello, world"); let zero = Hash::default(); - let tr0 = Transaction::new(&keypair, get_pubkey(&keypair), asset, zero); + let tr0 = Transaction::new(&keypair, keypair.pubkey(), asset, zero); assert!(tr0.verify()); } #[test] fn test_transfer() { let zero = Hash::default(); - let keypair0 = generate_keypair(); - let keypair1 = generate_keypair(); - let pubkey1 = get_pubkey(&keypair1); + let keypair0 = KeyPair::new(); + let keypair1 = KeyPair::new(); + let pubkey1 = keypair1.pubkey(); let asset = hash(b"hello, world"); let tr0 = Transaction::new(&keypair0, pubkey1, asset, zero); assert!(tr0.verify()); @@ -85,8 +84,8 @@ mod tests { #[test] fn test_bad_event_signature() { let zero = Hash::default(); - let keypair = generate_keypair(); - let pubkey = get_pubkey(&keypair); + let keypair = KeyPair::new(); + let pubkey = keypair.pubkey(); let mut tr = Transaction::new(&keypair, pubkey, hash(b"hello, world"), zero); tr.sign(&keypair); tr.asset = hash(b"goodbye cruel world"); // <-- attack! @@ -95,14 +94,14 @@ mod tests { #[test] fn test_hijack_attack() { - let keypair0 = generate_keypair(); - let keypair1 = generate_keypair(); - let thief_keypair = generate_keypair(); - let pubkey1 = get_pubkey(&keypair1); + let keypair0 = KeyPair::new(); + let keypair1 = KeyPair::new(); + let thief_keypair = KeyPair::new(); + let pubkey1 = keypair1.pubkey(); let zero = Hash::default(); let mut tr = Transaction::new(&keypair0, pubkey1, hash(b"hello, world"), zero); tr.sign(&keypair0); - tr.to = get_pubkey(&thief_keypair); // <-- attack! + tr.to = thief_keypair.pubkey(); // <-- attack! assert!(!tr.verify()); } }