all crypto functions

This commit is contained in:
debris 2016-09-09 10:49:08 +02:00
parent 03f5d3d4b0
commit ea5bee9a36
8 changed files with 239 additions and 31 deletions

View File

@ -1,6 +1,6 @@
use block_header::BlockHeader; use block_header::BlockHeader;
use compact_integer::CompactInteger; use compact_integer::CompactInteger;
use crypto::dhash; use crypto::dhash256;
use hash::H256; use hash::H256;
use merkle_root::merkle_root; use merkle_root::merkle_root;
use reader::{Deserializable, Reader, Error as ReaderError}; use reader::{Deserializable, Reader, Error as ReaderError};
@ -38,7 +38,7 @@ impl Deserializable for Block {
impl Block { impl Block {
pub fn hash(&self) -> H256 { pub fn hash(&self) -> H256 {
dhash(&serialize(&self.block_header)) dhash256(&serialize(&self.block_header))
} }
/// Returns block's merkle root. /// Returns block's merkle root.

View File

@ -1,6 +1,8 @@
use rcrypto::sha1::Sha1;
use rcrypto::sha2::Sha256; use rcrypto::sha2::Sha256;
use rcrypto::ripemd160::Ripemd160;
use rcrypto::digest::Digest; use rcrypto::digest::Digest;
use hash::H256; use hash::{H160, H256};
/// SHA-256 /// SHA-256
#[inline] #[inline]
@ -12,6 +14,46 @@ pub fn hash(input: &[u8]) -> H256 {
result result
} }
pub struct DHash160 {
sha256: Sha256,
ripemd: Ripemd160,
}
impl DHash160 {
pub fn new() -> Self {
DHash160 {
sha256: Sha256::new(),
ripemd: Ripemd160::new(),
}
}
}
impl Digest for DHash160 {
fn input(&mut self, d: &[u8]) {
self.sha256.input(d)
}
fn result(&mut self, out: &mut [u8]) {
let mut tmp = [0u8; 32];
self.sha256.result(&mut tmp);
self.ripemd.input(&tmp);
self.ripemd.result(out);
self.ripemd.reset();
}
fn reset(&mut self) {
self.sha256.reset();
}
fn output_bits(&self) -> usize {
160
}
fn block_size(&self) -> usize {
64
}
}
pub struct DHash256 { pub struct DHash256 {
hasher: Sha256, hasher: Sha256,
} }
@ -49,9 +91,49 @@ impl Digest for DHash256 {
} }
} }
/// RIPEMD160
#[inline]
pub fn ripemd160(input: &[u8]) -> H160 {
let mut result = [0u8; 20];
let mut hasher = Ripemd160::new();
hasher.input(input);
hasher.result(&mut result);
result
}
/// SHA-1
#[inline]
pub fn sha1(input: &[u8]) -> H160 {
let mut result = [0u8; 20];
let mut hasher = Sha1::new();
hasher.input(input);
hasher.result(&mut result);
result
}
/// SHA-256
#[inline]
pub fn sha256(input: &[u8]) -> H256 {
let mut result = [0u8; 32];
let mut hasher = Sha256::new();
hasher.input(input);
hasher.result(&mut result);
result
}
/// SHA-256 and RIPEMD160
#[inline]
pub fn dhash160(input: &[u8]) -> H160 {
let mut result = [0u8; 20];
let mut hasher = DHash160::new();
hasher.input(input);
hasher.result(&mut result);
result
}
/// Double SHA-256 /// Double SHA-256
#[inline] #[inline]
pub fn dhash(input: &[u8]) -> H256 { pub fn dhash256(input: &[u8]) -> H256 {
let mut result = [0u8; 32]; let mut result = [0u8; 32];
let mut hasher = DHash256::new(); let mut hasher = DHash256::new();
hasher.input(input); hasher.input(input);
@ -61,13 +143,41 @@ pub fn dhash(input: &[u8]) -> H256 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::dhash; use super::{ripemd160, sha1, sha256, dhash160, dhash256};
use hex::FromHex; use hex::FromHex;
#[test]
fn test_ripemd160() {
let expected = "108f07b8382412612c048d07d13f814118445acd".from_hex().unwrap();
let result = ripemd160(b"hello");
assert_eq!(result.to_vec(), expected);
}
#[test]
fn test_sha1() {
let expected = "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d".from_hex().unwrap();
let result = sha1(b"hello");
assert_eq!(result.to_vec(), expected);
}
#[test]
fn test_sha256() {
let expected = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824".from_hex().unwrap();
let result = sha256(b"hello");
assert_eq!(result.to_vec(), expected);
}
#[test]
fn test_dhash160() {
let expected = "b6a9c8c230722b7c748331a8b450f05566dc7d0f".from_hex().unwrap();
let result = dhash160(b"hello");
assert_eq!(result.to_vec(), expected);
}
#[test] #[test]
fn test_double_hash() { fn test_dhash256() {
let expected = "9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50".from_hex().unwrap(); let expected = "9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50".from_hex().unwrap();
let result = dhash(b"hello"); let result = dhash256(b"hello");
assert_eq!(result.to_vec(), expected); assert_eq!(result.to_vec(), expected);
} }
} }

View File

@ -1,8 +1,8 @@
use crypto::dhash; use crypto::dhash256;
/// Data checksum /// Data checksum
pub fn checksum(data: &[u8]) -> [u8; 4] { pub fn checksum(data: &[u8]) -> [u8; 4] {
let mut result = [0u8; 4]; let mut result = [0u8; 4];
result.copy_from_slice(&dhash(data)[0..4]); result.copy_from_slice(&dhash256(data)[0..4]);
result result
} }

View File

@ -86,7 +86,7 @@ impl KeyPair {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crypto::dhash; use crypto::dhash256;
use keys::Public; use keys::Public;
use super::KeyPair; use super::KeyPair;
@ -120,25 +120,25 @@ mod tests {
} }
fn check_sign(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool { fn check_sign(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool {
let message = dhash(raw_message); let message = dhash256(raw_message);
let kp = KeyPair::from_private(secret.into()).unwrap(); let kp = KeyPair::from_private(secret.into()).unwrap();
kp.private().sign(&message).unwrap() == signature.into() kp.private().sign(&message).unwrap() == signature.into()
} }
fn check_verify(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool { fn check_verify(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool {
let message = dhash(raw_message); let message = dhash256(raw_message);
let kp = KeyPair::from_private(secret.into()).unwrap(); let kp = KeyPair::from_private(secret.into()).unwrap();
kp.public().verify(&message, &signature.into()).unwrap() kp.public().verify(&message, &signature.into()).unwrap()
} }
fn check_sign_compact(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool { fn check_sign_compact(secret: &'static str, raw_message: &[u8], signature: &'static str) -> bool {
let message = dhash(raw_message); let message = dhash256(raw_message);
let kp = KeyPair::from_private(secret.into()).unwrap(); let kp = KeyPair::from_private(secret.into()).unwrap();
kp.private().sign_compact(&message).unwrap() == signature.into() kp.private().sign_compact(&message).unwrap() == signature.into()
} }
fn check_recover_compact(secret: &'static str, raw_message: &[u8]) -> bool { fn check_recover_compact(secret: &'static str, raw_message: &[u8]) -> bool {
let message = dhash(raw_message); let message = dhash256(raw_message);
let kp = KeyPair::from_private(secret.into()).unwrap(); let kp = KeyPair::from_private(secret.into()).unwrap();
let signature = kp.private().sign_compact(&message).unwrap(); let signature = kp.private().sign_compact(&message).unwrap();
let recovered = Public::recover_compact(&message, &signature).unwrap(); let recovered = Public::recover_compact(&message, &signature).unwrap();

View File

@ -2,10 +2,8 @@ use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use secp256k1::key; use secp256k1::key;
use secp256k1::{Message as SecpMessage, RecoveryId, RecoverableSignature, Error as SecpError, Signature as SecpSignature}; use secp256k1::{Message as SecpMessage, RecoveryId, RecoverableSignature, Error as SecpError, Signature as SecpSignature};
use rcrypto::sha2::Sha256;
use rcrypto::ripemd160::Ripemd160;
use rcrypto::digest::Digest;
use hex::ToHex; use hex::ToHex;
use crypto::dhash160;
use hash::{H264, H520}; use hash::{H264, H520};
use keys::{AddressHash, Error, CompactSignature, Signature, Message, SECP256K1}; use keys::{AddressHash, Error, CompactSignature, Signature, Message, SECP256K1};
@ -16,15 +14,7 @@ pub enum Public {
impl Public { impl Public {
pub fn address_hash(&self) -> AddressHash { pub fn address_hash(&self) -> AddressHash {
let mut tmp = [0u8; 32]; dhash160(self)
let mut result = [0u8; 20];
let mut sha2 = Sha256::new();
let mut rmd = Ripemd160::new();
sha2.input(self);
sha2.result(&mut tmp);
rmd.input(&tmp);
rmd.result(&mut result);
result
} }
pub fn verify(&self, message: &Message, signature: &Signature) -> Result<bool, Error> { pub fn verify(&self, message: &Message, signature: &Signature) -> Result<bool, Error> {

View File

@ -1,4 +1,4 @@
use crypto::dhash; use crypto::dhash256;
use hash::{H256, H512}; use hash::{H256, H512};
#[inline] #[inline]
@ -19,14 +19,14 @@ pub fn merkle_root(hashes: &[H256]) -> H256 {
let mut row = vec![]; let mut row = vec![];
let mut i = 0; let mut i = 0;
while i + 1 < hashes.len() { while i + 1 < hashes.len() {
row.push(dhash(&concat(&hashes[i], &hashes[i + 1]))); row.push(dhash256(&concat(&hashes[i], &hashes[i + 1])));
i += 2 i += 2
} }
// duplicate the last element if len is not even // duplicate the last element if len is not even
if hashes.len() % 2 == 1 { if hashes.len() % 2 == 1 {
let last = hashes[hashes.len() - 1]; let last = hashes[hashes.len() - 1];
row.push(dhash(&concat(&last, &last))); row.push(dhash256(&concat(&last, &last)));
} }
merkle_root(&row) merkle_root(&row)

View File

@ -1,6 +1,7 @@
use keys::{Public, Signature}; use keys::{Public, Signature};
use hash::H256; use hash::H256;
use transaction::{Transaction, SEQUENCE_LOCKTIME_DISABLE_FLAG}; use transaction::{Transaction, SEQUENCE_LOCKTIME_DISABLE_FLAG};
use crypto::{sha1, sha256, dhash160, dhash256, ripemd160};
use script::{script, Script, Num, VerificationFlags, Opcode, Error, Instruction}; use script::{script, Script, Num, VerificationFlags, Opcode, Error, Instruction};
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
@ -560,6 +561,33 @@ pub fn eval_script(
return Err(Error::EqualVerify); return Err(Error::EqualVerify);
} }
}, },
// several opcodes here
Opcode::OP_RIPEMD160 => {
try!(require_not_empty(stack));
let v = ripemd160(&stack.pop().unwrap());
stack.push(v.to_vec());
},
Opcode::OP_SHA1 => {
try!(require_not_empty(stack));
let v = sha1(&stack.pop().unwrap());
stack.push(v.to_vec());
},
Opcode::OP_SHA256 => {
try!(require_not_empty(stack));
let v = sha256(&stack.pop().unwrap());
stack.push(v.to_vec());
},
Opcode::OP_HASH160 => {
try!(require_not_empty(stack));
let v = dhash160(&stack.pop().unwrap());
stack.push(v.to_vec());
},
Opcode::OP_HASH256 => {
try!(require_not_empty(stack));
let v = dhash256(&stack.pop().unwrap());
stack.push(v.to_vec());
},
_ => (), _ => (),
}, },
} }
@ -726,4 +754,84 @@ mod tests {
let result = Err(Error::InvalidStackOperation); let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, vec![]); basic_test(&script, result, vec![]);
} }
#[test]
fn test_hash256() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_HASH256)
.into_script();
let result = Ok(true);
let stack = vec!["9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50".from_hex().unwrap()];
basic_test(&script, result, stack);
}
#[test]
fn test_hash256_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_HASH256)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, vec![]);
}
#[test]
fn test_ripemd160() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_RIPEMD160)
.into_script();
let result = Ok(true);
let stack = vec!["108f07b8382412612c048d07d13f814118445acd".from_hex().unwrap()];
basic_test(&script, result, stack);
}
#[test]
fn test_ripemd160_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_RIPEMD160)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, vec![]);
}
#[test]
fn test_sha1() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_SHA1)
.into_script();
let result = Ok(true);
let stack = vec!["aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d".from_hex().unwrap()];
basic_test(&script, result, stack);
}
#[test]
fn test_sha1_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_SHA1)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, vec![]);
}
#[test]
fn test_sha256() {
let script = Builder::default()
.push_data(b"hello")
.push_opcode(Opcode::OP_SHA256)
.into_script();
let result = Ok(true);
let stack = vec!["2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824".from_hex().unwrap()];
basic_test(&script, result, stack);
}
#[test]
fn test_sha256_invalid_stack() {
let script = Builder::default()
.push_opcode(Opcode::OP_SHA256)
.into_script();
let result = Err(Error::InvalidStackOperation);
basic_test(&script, result, vec![]);
}
} }

View File

@ -3,7 +3,7 @@
//! https://en.bitcoin.it/wiki/Protocol_documentation#tx //! https://en.bitcoin.it/wiki/Protocol_documentation#tx
use reader::{Deserializable, Reader, Error as ReaderError}; use reader::{Deserializable, Reader, Error as ReaderError};
use crypto::dhash; use crypto::dhash256;
use hash::H256; use hash::H256;
use stream::{Serializable, Stream, serialize}; use stream::{Serializable, Stream, serialize};
use compact_integer::CompactInteger; use compact_integer::CompactInteger;
@ -147,7 +147,7 @@ impl Deserializable for Transaction {
impl Transaction { impl Transaction {
pub fn hash(&self) -> H256 { pub fn hash(&self) -> H256 {
dhash(&serialize(self)) dhash256(&serialize(self))
} }
} }