parity_crypto/
digest.rs

1// Copyright 2020 Parity Technologies
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::marker::PhantomData;
10use std::ops::Deref;
11
12use digest::generic_array::{
13	typenum::{U20, U32, U64},
14	GenericArray,
15};
16use sha2::Digest as RDigest;
17
18/// The message digest.
19pub struct Digest<T>(InnerDigest, PhantomData<T>);
20
21enum InnerDigest {
22	Sha256(GenericArray<u8, U32>),
23	Sha512(GenericArray<u8, U64>),
24	Ripemd160(GenericArray<u8, U20>),
25}
26
27impl<T> Deref for Digest<T> {
28	type Target = [u8];
29	fn deref(&self) -> &Self::Target {
30		match self.0 {
31			InnerDigest::Sha256(ref d) => &d[..],
32			InnerDigest::Sha512(ref d) => &d[..],
33			InnerDigest::Ripemd160(ref d) => &d[..],
34		}
35	}
36}
37
38/// Single-step sha256 digest computation.
39pub fn sha256(data: &[u8]) -> Digest<Sha256> {
40	let mut hasher = Hasher::sha256();
41	hasher.update(data);
42	hasher.finish()
43}
44
45/// Single-step sha512 digest computation.
46pub fn sha512(data: &[u8]) -> Digest<Sha512> {
47	let mut hasher = Hasher::sha512();
48	hasher.update(data);
49	hasher.finish()
50}
51
52/// Single-step ripemd160 digest computation.
53pub fn ripemd160(data: &[u8]) -> Digest<Ripemd160> {
54	let mut hasher = Hasher::ripemd160();
55	hasher.update(data);
56	hasher.finish()
57}
58
59#[derive(Debug)]
60pub enum Sha256 {}
61#[derive(Debug)]
62pub enum Sha512 {}
63#[derive(Debug)]
64pub enum Ripemd160 {}
65
66/// Stateful digest computation.
67pub struct Hasher<T>(Inner, PhantomData<T>);
68
69enum Inner {
70	Sha256(sha2::Sha256),
71	Sha512(sha2::Sha512),
72	Ripemd160(ripemd160::Ripemd160),
73}
74
75impl Hasher<Sha256> {
76	pub fn sha256() -> Hasher<Sha256> {
77		Hasher(Inner::Sha256(sha2::Sha256::default()), PhantomData)
78	}
79}
80
81impl Hasher<Sha512> {
82	pub fn sha512() -> Hasher<Sha512> {
83		Hasher(Inner::Sha512(sha2::Sha512::default()), PhantomData)
84	}
85}
86
87impl Hasher<Ripemd160> {
88	pub fn ripemd160() -> Hasher<Ripemd160> {
89		Hasher(Inner::Ripemd160(ripemd160::Ripemd160::default()), PhantomData)
90	}
91}
92
93impl<T> Hasher<T> {
94	pub fn update(&mut self, data: &[u8]) {
95		match self.0 {
96			Inner::Sha256(ref mut ctx) => ctx.update(data),
97			Inner::Sha512(ref mut ctx) => ctx.update(data),
98			Inner::Ripemd160(ref mut ctx) => ctx.update(data),
99		}
100	}
101
102	pub fn finish(self) -> Digest<T> {
103		match self.0 {
104			Inner::Sha256(ctx) => Digest(InnerDigest::Sha256(ctx.finalize()), PhantomData),
105			Inner::Sha512(ctx) => Digest(InnerDigest::Sha512(ctx.finalize()), PhantomData),
106			Inner::Ripemd160(ctx) => Digest(InnerDigest::Ripemd160(ctx.finalize()), PhantomData),
107		}
108	}
109}