1use crate::TinkError;
20use digest::Digest;
21use subtle::ConstantTimeEq;
22use tink_proto::HashType;
23
24mod hkdf;
25pub use self::hkdf::*;
26pub mod random;
27
28pub fn get_hash_digest_size(hash: HashType) -> Result<usize, TinkError> {
30 match hash {
31 HashType::Sha1 => Ok(20),
32 HashType::Sha224 => Ok(28),
33 HashType::Sha256 => Ok(32),
34 HashType::Sha384 => Ok(48),
35 HashType::Sha512 => Ok(64),
36 _ => Err("invalid hash algorithm".into()),
37 }
38}
39
40pub enum HashFunc {
42 Sha1(sha1::Sha1),
43 Sha224(sha2::Sha224),
44 Sha256(sha2::Sha256),
45 Sha384(sha2::Sha384),
46 Sha512(sha2::Sha512),
47}
48
49pub fn get_hash_func(hash: HashType) -> Option<HashFunc> {
51 match hash {
52 HashType::Sha1 => Some(HashFunc::Sha1(sha1::Sha1::new())),
53 HashType::Sha224 => Some(HashFunc::Sha224(sha2::Sha224::new())),
54 HashType::Sha256 => Some(HashFunc::Sha256(sha2::Sha256::new())),
55 HashType::Sha384 => Some(HashFunc::Sha384(sha2::Sha384::new())),
56 HashType::Sha512 => Some(HashFunc::Sha512(sha2::Sha512::new())),
57 _ => None,
58 }
59}
60
61pub fn compute_hash(hash_fn: &mut HashFunc, data: &[u8]) -> Result<Vec<u8>, TinkError> {
63 Ok(match hash_fn {
64 HashFunc::Sha1(h) => compute_hash_with(h, data),
65 HashFunc::Sha224(h) => compute_hash_with(h, data),
66 HashFunc::Sha256(h) => compute_hash_with(h, data),
67 HashFunc::Sha384(h) => compute_hash_with(h, data),
68 HashFunc::Sha512(h) => compute_hash_with(h, data),
69 })
70}
71
72fn compute_hash_with<T>(hash_func: &mut T, data: &[u8]) -> Vec<u8>
74where
75 T: digest::Digest + digest::Reset + digest::FixedOutputReset,
76{
77 Digest::reset(hash_func);
78 Digest::update(hash_func, data);
79 Digest::finalize_reset(hash_func).to_vec()
80}
81
82pub fn constant_time_compare(left: &[u8], right: &[u8]) -> bool {
84 left.ct_eq(right).into()
85}