| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- /* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2023 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- //! HMAC simplementation.
- //! https://en.wikipedia.org/wiki/Hmac
- use digest::{
- core_api::Block, crypto_common::BlockSizeUser, Digest, FixedOutput, Output, OutputSizeUser,
- Update,
- };
- const IPAD: u8 = 0x36;
- const OPAD: u8 = 0x5C;
- fn get_der_key<D: Digest + BlockSizeUser + Clone>(key: &[u8]) -> Block<D> {
- let mut der_key = Block::<D>::default();
- // The key that HMAC processes must be the same as the block size
- // of the underlying hash function. If the provided key is smaller
- // than that, we just pad it with zeroes. If it's larger, we hash
- // it and then pad it with zeroes.
- if key.len() <= der_key.len() {
- der_key[..key.len()].copy_from_slice(key);
- return der_key
- }
- let hash = D::digest(key);
- // All commonly used hash functions have block size bigger than
- // output hash size, but to be extra rigorous we handle the
- // potential uncommon cases as well. The condition is calculated
- // at compile time, so this branch gets removed from final binary.
- if hash.len() <= der_key.len() {
- der_key[..hash.len()].copy_from_slice(&hash);
- } else {
- let n = der_key.len();
- der_key.copy_from_slice(&hash[..n]);
- }
- der_key
- }
- /// HMAC for arbitrary hash functions that implement `Digest`
- /// and `BlockSizeUser` traits.
- #[derive(Clone)]
- pub struct Hmac<D: Digest + BlockSizeUser + Clone> {
- digest: D,
- opad_key: Block<D>,
- }
- impl<D: Digest + BlockSizeUser + Clone> Hmac<D> {
- /// Initialize a new `Hmac` with the given key.
- #[inline]
- pub fn new_from_slice(key: &[u8]) -> Self {
- let der_key = get_der_key::<D>(key);
- let mut ipad_key = der_key.clone();
- for b in ipad_key.iter_mut() {
- *b ^= IPAD;
- }
- let mut digest = D::new();
- digest.update(&ipad_key);
- let mut opad_key = der_key;
- for b in opad_key.iter_mut() {
- *b ^= OPAD;
- }
- Self { digest, opad_key }
- }
- /// Finalize the HMAC
- pub fn finalize(self) -> Output<D> {
- Output::<D>::clone_from_slice(&self.finalize_fixed())
- }
- }
- impl<D: Digest + BlockSizeUser + Clone> FixedOutput for Hmac<D> {
- fn finalize_into(self, out: &mut Output<Self>) {
- let mut h = D::new();
- h.update(&self.opad_key);
- h.update(&self.digest.finalize());
- h.finalize_into(out);
- }
- }
- impl<D: Digest + BlockSizeUser + Clone> OutputSizeUser for Hmac<D> {
- type OutputSize = D::OutputSize;
- }
- impl<D: Digest + BlockSizeUser + Clone> Update for Hmac<D> {
- /// Update the HMAC with the given data.
- fn update(&mut self, data: &[u8]) {
- self.digest.update(data);
- }
- }
|