Merge pull request #26 from gavofyork/gav
Additional work & convenience functions on crypto, bytes & hash.
This commit is contained in:
commit
d4cbad11ca
20
src/bytes.rs
20
src/bytes.rs
@ -306,10 +306,28 @@ impl <T>FromBytes for T where T: FixedHash {
|
|||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
|
||||||
let mut res: T = mem::uninitialized();
|
let mut res: T = mem::uninitialized();
|
||||||
ptr::copy(bytes.as_ptr(), res.mut_bytes().as_mut_ptr(), T::size());
|
ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size());
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: tests and additional docs for these two.
|
||||||
|
|
||||||
|
/// Simple trait to allow for raw population of a Sized object from a byte slice.
|
||||||
|
pub trait Populatable {
|
||||||
|
/// Populate self from byte slice `d` in a raw fashion.
|
||||||
|
fn populate_raw(&mut self, d: &[u8]);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Populatable for T where T: Sized {
|
||||||
|
fn populate_raw(&mut self, d: &[u8]) {
|
||||||
|
use std::mem;
|
||||||
|
use std::slice;
|
||||||
|
use std::io::Write;
|
||||||
|
unsafe {
|
||||||
|
slice::from_raw_parts_mut(self as *mut T as *mut u8, mem::size_of::<T>())
|
||||||
|
}.write(&d).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,9 +3,24 @@ use secp256k1::Secp256k1;
|
|||||||
use secp256k1::key;
|
use secp256k1::key;
|
||||||
use rand::os::OsRng;
|
use rand::os::OsRng;
|
||||||
|
|
||||||
pub type Secret=H256;
|
pub type Secret = H256;
|
||||||
pub type Public=H512;
|
pub type Public = H512;
|
||||||
pub type Signature=H520;
|
pub type Signature = H520;
|
||||||
|
|
||||||
|
impl Signature {
|
||||||
|
/// Create a new signature from the R, S and V componenets.
|
||||||
|
pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Signature {
|
||||||
|
use std::ptr;
|
||||||
|
let mut ret: Signature = Signature::new();
|
||||||
|
unsafe {
|
||||||
|
let retslice: &mut [u8] = &mut ret;
|
||||||
|
ptr::copy(r.as_ptr(), retslice.as_mut_ptr(), 32);
|
||||||
|
ptr::copy(s.as_ptr(), retslice.as_mut_ptr().offset(32), 32);
|
||||||
|
}
|
||||||
|
ret[64] = v;
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CryptoError {
|
pub enum CryptoError {
|
||||||
@ -92,6 +107,9 @@ impl KeyPair {
|
|||||||
pub fn secret(&self) -> &Secret {
|
pub fn secret(&self) -> &Secret {
|
||||||
&self.secret
|
&self.secret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sign a message with our secret key.
|
||||||
|
pub fn sign(&self, message: &H256) -> Result<Signature, CryptoError> { sign(&self.secret, message) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recovers Public key from signed message hash.
|
/// Recovers Public key from signed message hash.
|
||||||
@ -102,8 +120,11 @@ pub fn recover(signature: &Signature, message: &H256) -> Result<Public, CryptoEr
|
|||||||
let publ = try!(context.recover(&try!(Message::from_slice(&message)), &rsig));
|
let publ = try!(context.recover(&try!(Message::from_slice(&message)), &rsig));
|
||||||
let serialized = publ.serialize_vec(&context, false);
|
let serialized = publ.serialize_vec(&context, false);
|
||||||
let p: Public = Public::from_slice(&serialized[1..65]);
|
let p: Public = Public::from_slice(&serialized[1..65]);
|
||||||
|
//TODO: check if it's the zero key and fail if so.
|
||||||
|
|
||||||
Ok(p)
|
Ok(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns siganture of message hash.
|
/// Returns siganture of message hash.
|
||||||
pub fn sign(secret: &Secret, message: &H256) -> Result<Signature, CryptoError> {
|
pub fn sign(secret: &Secret, message: &H256) -> Result<Signature, CryptoError> {
|
||||||
use secp256k1::*;
|
use secp256k1::*;
|
||||||
@ -116,6 +137,16 @@ pub fn sign(secret: &Secret, message: &H256) -> Result<Signature, CryptoError> {
|
|||||||
signature[64] = rec_id.to_i32() as u8;
|
signature[64] = rec_id.to_i32() as u8;
|
||||||
Ok(signature)
|
Ok(signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if each component of the signature is in range.
|
||||||
|
pub fn is_valid(sig: &Signature) -> bool {
|
||||||
|
sig[64] <= 1 &&
|
||||||
|
H256::from_slice(&sig[0..32]) < h256_from_hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") &&
|
||||||
|
H256::from_slice(&sig[32..64]) < h256_from_hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141") &&
|
||||||
|
H256::from_slice(&sig[32..64]) >= h256_from_u64(1) &&
|
||||||
|
H256::from_slice(&sig[0..32]) >= h256_from_u64(1)
|
||||||
|
}
|
||||||
|
|
||||||
/// Verify signature.
|
/// Verify signature.
|
||||||
pub fn verify(public: &Public, signature: &Signature, message: &H256) -> Result<bool, CryptoError> {
|
pub fn verify(public: &Public, signature: &Signature, message: &H256) -> Result<bool, CryptoError> {
|
||||||
use secp256k1::*;
|
use secp256k1::*;
|
||||||
@ -142,6 +173,8 @@ mod tests {
|
|||||||
use hash::*;
|
use hash::*;
|
||||||
use crypto::*;
|
use crypto::*;
|
||||||
|
|
||||||
|
// TODO: tests for sign/recover roundtrip, at least.
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_signature() {
|
fn test_signature() {
|
||||||
let pair = KeyPair::create().unwrap();
|
let pair = KeyPair::create().unwrap();
|
||||||
@ -154,14 +187,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_key() {
|
fn test_invalid_key() {
|
||||||
assert!(KeyPair::from_secret(Secret::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()).is_err());
|
assert!(KeyPair::from_secret(h256_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")).is_err());
|
||||||
assert!(KeyPair::from_secret(Secret::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap()).is_err());
|
assert!(KeyPair::from_secret(h256_from_hex("0000000000000000000000000000000000000000000000000000000000000000")).is_err());
|
||||||
assert!(KeyPair::from_secret(Secret::from_str("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap()).is_err());
|
assert!(KeyPair::from_secret(h256_from_hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141")).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_key() {
|
fn test_key() {
|
||||||
let pair = KeyPair::from_secret(Secret::from_str("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2").unwrap()).unwrap();
|
let pair = KeyPair::from_secret(h256_from_hex("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2")).unwrap();
|
||||||
assert_eq!(pair.public().hex(), "101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c");
|
assert_eq!(pair.public().hex(), "101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
40
src/hash.rs
40
src/hash.rs
@ -5,6 +5,7 @@ use std::fmt;
|
|||||||
use std::ops;
|
use std::ops;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::{Index, IndexMut, Deref, DerefMut, BitOr, BitAnd};
|
use std::ops::{Index, IndexMut, Deref, DerefMut, BitOr, BitAnd};
|
||||||
|
use std::cmp::{PartialOrd, Ordering};
|
||||||
use rustc_serialize::hex::*;
|
use rustc_serialize::hex::*;
|
||||||
use error::EthcoreError;
|
use error::EthcoreError;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
@ -21,7 +22,7 @@ pub trait FixedHash: Sized + BytesConvertable {
|
|||||||
fn random() -> Self;
|
fn random() -> Self;
|
||||||
fn randomize(&mut self);
|
fn randomize(&mut self);
|
||||||
fn size() -> usize;
|
fn size() -> usize;
|
||||||
fn mut_bytes(&mut self) -> &mut [u8];
|
fn as_slice_mut(&mut self) -> &mut [u8];
|
||||||
fn from_slice(src: &[u8]) -> Self;
|
fn from_slice(src: &[u8]) -> Self;
|
||||||
fn clone_from_slice(&mut self, src: &[u8]) -> usize;
|
fn clone_from_slice(&mut self, src: &[u8]) -> usize;
|
||||||
fn shift_bloom<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash;
|
fn shift_bloom<'a, T>(&'a mut self, b: &T) -> &'a mut Self where T: FixedHash;
|
||||||
@ -77,7 +78,7 @@ macro_rules! impl_hash {
|
|||||||
$size
|
$size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mut_bytes(&mut self) -> &mut [u8] {
|
fn as_slice_mut(&mut self) -> &mut [u8] {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ macro_rules! impl_hash {
|
|||||||
ptr += 1;
|
ptr += 1;
|
||||||
}
|
}
|
||||||
index &= mask;
|
index &= mask;
|
||||||
ret.mut_bytes()[m - 1 - index / 8] |= 1 << (index % 8);
|
ret.as_slice_mut()[m - 1 - index / 8] |= 1 << (index % 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret
|
ret
|
||||||
@ -208,6 +209,19 @@ macro_rules! impl_hash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for $from {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
for i in 0..$size {
|
||||||
|
if self.0[i] > other.0[i] {
|
||||||
|
return Some(Ordering::Greater);
|
||||||
|
} else if self.0[i] < other.0[i] {
|
||||||
|
return Some(Ordering::Less);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(Ordering::Equal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Hash for $from {
|
impl Hash for $from {
|
||||||
fn hash<H>(&self, state: &mut H) where H: Hasher {
|
fn hash<H>(&self, state: &mut H) where H: Hasher {
|
||||||
state.write(&self.0);
|
state.write(&self.0);
|
||||||
@ -340,6 +354,26 @@ impl From<Address> for H256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn h256_from_hex(s: &str) -> H256 {
|
||||||
|
use std::str::FromStr;
|
||||||
|
H256::from_str(s).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn h256_from_u64(n: u64) -> H256 {
|
||||||
|
use uint::U256;
|
||||||
|
H256::from(&U256::from(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn address_from_hex(s: &str) -> Address {
|
||||||
|
use std::str::FromStr;
|
||||||
|
Address::from_str(s).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn address_from_u64(n: u64) -> Address {
|
||||||
|
let h256 = h256_from_u64(n);
|
||||||
|
From::from(h256)
|
||||||
|
}
|
||||||
|
|
||||||
impl_hash!(H32, 4);
|
impl_hash!(H32, 4);
|
||||||
impl_hash!(H64, 8);
|
impl_hash!(H64, 8);
|
||||||
impl_hash!(H128, 16);
|
impl_hash!(H128, 16);
|
||||||
|
@ -193,8 +193,11 @@ impl Encoder for BasicEncoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ()
|
fn emit_raw(&mut self, bytes: &[u8]) -> () {
|
||||||
{
|
self.bytes.append_slice(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> () {
|
||||||
// get len before inserting a list
|
// get len before inserting a list
|
||||||
let before_len = self.bytes.len();
|
let before_len = self.bytes.len();
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ pub trait Decoder: Sized {
|
|||||||
where F: FnOnce(&[u8]) -> Result<T, DecoderError>;
|
where F: FnOnce(&[u8]) -> Result<T, DecoderError>;
|
||||||
|
|
||||||
fn as_list(&self) -> Result<Vec<Self>, DecoderError>;
|
fn as_list(&self) -> Result<Vec<Self>, DecoderError>;
|
||||||
|
|
||||||
|
fn as_raw(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Decodable: Sized {
|
pub trait Decodable: Sized {
|
||||||
@ -185,6 +187,7 @@ pub trait View<'a, 'view>: Sized {
|
|||||||
pub trait Encoder {
|
pub trait Encoder {
|
||||||
fn emit_value(&mut self, bytes: &[u8]) -> ();
|
fn emit_value(&mut self, bytes: &[u8]) -> ();
|
||||||
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ();
|
fn emit_list<F>(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> ();
|
||||||
|
fn emit_raw(&mut self, bytes: &[u8]) -> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Encodable {
|
pub trait Encodable {
|
||||||
|
@ -305,6 +305,10 @@ impl<'a> Decoder for BasicDecoder<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_raw(&self) -> &[u8] {
|
||||||
|
self.rlp.raw()
|
||||||
|
}
|
||||||
|
|
||||||
fn as_list(&self) -> Result<Vec<Self>, DecoderError> {
|
fn as_list(&self) -> Result<Vec<Self>, DecoderError> {
|
||||||
let v: Vec<BasicDecoder<'a>> = self.rlp.iter()
|
let v: Vec<BasicDecoder<'a>> = self.rlp.iter()
|
||||||
.map(| i | BasicDecoder::new(i))
|
.map(| i | BasicDecoder::new(i))
|
||||||
|
@ -27,7 +27,7 @@ impl<T> Hashable for T where T: BytesConvertable {
|
|||||||
let mut keccak = Keccak::new_keccak256();
|
let mut keccak = Keccak::new_keccak256();
|
||||||
keccak.update(self.bytes());
|
keccak.update(self.bytes());
|
||||||
let mut ret: H256 = uninitialized();
|
let mut ret: H256 = uninitialized();
|
||||||
keccak.finalize(ret.mut_bytes());
|
keccak.finalize(ret.as_slice_mut());
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,7 +686,7 @@ mod tests {
|
|||||||
0 => encode(&j),
|
0 => encode(&j),
|
||||||
_ => {
|
_ => {
|
||||||
let mut h = H256::new();
|
let mut h = H256::new();
|
||||||
h.mut_bytes()[31] = j as u8;
|
h.as_slice_mut()[31] = j as u8;
|
||||||
encode(&h)
|
encode(&h)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user