extern crate openssl;
use errors::common::CommonError;
use self::openssl::hash::{hash2, MessageDigest, Hasher, DigestBytes};
pub const HASH_OUTPUT_LEN: usize = 32;
pub struct Digest {
data: DigestBytes
}
impl Digest {
fn new(data: DigestBytes) -> Digest {
Digest {
data: data
}
}
pub fn to_vec(&self) -> Vec<u8> {
self.data.to_vec()
}
}
pub struct Hash {}
impl Hash {
pub fn new_context() -> Result<Hasher, CommonError> {
Ok(Hasher::new(MessageDigest::sha256())?)
}
pub fn hash_empty() -> Result<Digest, CommonError> {
Ok(Digest::new(hash2(MessageDigest::sha256(), &[])?))
}
pub fn hash_leaf<T>(leaf: &T) -> Result<Digest, CommonError> where T: Hashable {
let mut ctx = Hash::new_context()?;
ctx.update(&[0x00])?;
leaf.update_context(&mut ctx)?;
Ok(Digest::new(ctx.finish2()?))
}
pub fn hash_nodes<T>(left: &T, right: &T) -> Result<Digest, CommonError> where T: Hashable {
let mut ctx = Hash::new_context()?;
ctx.update(&[0x01])?;
left.update_context(&mut ctx)?;
right.update_context(&mut ctx)?;
Ok(Digest::new(ctx.finish2()?))
}
}
pub trait Hashable {
fn update_context(&self, context: &mut Hasher) -> Result<(), CommonError>;
}
impl <T: AsRef<[u8]>> Hashable for T {
fn update_context(&self, context: &mut Hasher) -> Result<(), CommonError> {
Ok(context.update(self.as_ref())?)
}
}