hmac.rs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. //! HMAC simplementation.
  2. //! https://en.wikipedia.org/wiki/Hmac
  3. use digest::{
  4. core_api::Block, crypto_common::BlockSizeUser, Digest, FixedOutput, Output, OutputSizeUser,
  5. Update,
  6. };
  7. const IPAD: u8 = 0x36;
  8. const OPAD: u8 = 0x5C;
  9. fn get_der_key<D: Digest + BlockSizeUser + Clone>(key: &[u8]) -> Block<D> {
  10. let mut der_key = Block::<D>::default();
  11. // The key that HMAC processes must be the same as the block size
  12. // of the underlying hash function. If the provided key is smaller
  13. // than that, we just pad it with zeroes. If it's larger, we hash
  14. // it and then pad it with zeroes.
  15. if key.len() <= der_key.len() {
  16. der_key[..key.len()].copy_from_slice(key);
  17. return der_key
  18. }
  19. let hash = D::digest(key);
  20. // All commonly used hash functions have block size bigger than
  21. // output hash size, but to be extra rigorous we handle the
  22. // potential uncommon cases as well. The condition is calculated
  23. // at compile time, so this branch gets removed from final binary.
  24. if hash.len() <= der_key.len() {
  25. der_key[..hash.len()].copy_from_slice(&hash);
  26. } else {
  27. let n = der_key.len();
  28. der_key.copy_from_slice(&hash[..n]);
  29. }
  30. der_key
  31. }
  32. /// HMAC for arbitrary hash functions that implement `Digest`
  33. /// and `BlockSizeUser` traits.
  34. #[derive(Clone)]
  35. pub struct Hmac<D: Digest + BlockSizeUser + Clone> {
  36. digest: D,
  37. opad_key: Block<D>,
  38. }
  39. impl<D: Digest + BlockSizeUser + Clone> Hmac<D> {
  40. /// Initialize a new `Hmac` with the given key.
  41. #[inline]
  42. pub fn new_from_slice(key: &[u8]) -> Self {
  43. let der_key = get_der_key::<D>(key);
  44. let mut ipad_key = der_key.clone();
  45. for b in ipad_key.iter_mut() {
  46. *b ^= IPAD;
  47. }
  48. let mut digest = D::new();
  49. digest.update(&ipad_key);
  50. let mut opad_key = der_key;
  51. for b in opad_key.iter_mut() {
  52. *b ^= OPAD;
  53. }
  54. Self { digest, opad_key }
  55. }
  56. /// Finalize the HMAC
  57. pub fn finalize(self) -> Output<D> {
  58. Output::<D>::clone_from_slice(&self.finalize_fixed())
  59. }
  60. }
  61. impl<D: Digest + BlockSizeUser + Clone> FixedOutput for Hmac<D> {
  62. fn finalize_into(self, out: &mut Output<Self>) {
  63. let mut h = D::new();
  64. h.update(&self.opad_key);
  65. h.update(&self.digest.finalize());
  66. h.finalize_into(out);
  67. }
  68. }
  69. impl<D: Digest + BlockSizeUser + Clone> OutputSizeUser for Hmac<D> {
  70. type OutputSize = D::OutputSize;
  71. }
  72. impl<D: Digest + BlockSizeUser + Clone> Update for Hmac<D> {
  73. /// Update the HMAC with the given data.
  74. fn update(&mut self, data: &[u8]) {
  75. self.digest.update(data);
  76. }
  77. }