Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hmac: 2018 edition and crypto-mac crate upgrade #33

Merged
merged 1 commit into from
May 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 18 additions & 48 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ members = [

[patch.crates-io]
aes = { git = "https://github.com/RustCrypto/block-ciphers" }
block-buffer = { git = "https://github.com/RustCrypto/utils" }
block-cipher = { git = "https://github.com/RustCrypto/traits" }
crypto-mac = { git = "https://github.com/RustCrypto/traits" }
digest = { git = "https://github.com/RustCrypto/traits" }
dbl = { git = "https://github.com/RustCrypto/utils" }
des = { git = "https://github.com/RustCrypto/block-ciphers" }
md-5 = { git = "https://github.com/RustCrypto/hashes" }
sha2 = { git = "https://github.com/RustCrypto/hashes" }
11 changes: 6 additions & 5 deletions hmac/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ repository = "https://github.com/RustCrypto/MACs"
keywords = ["crypto", "mac", "hmac", "digest"]
categories = ["cryptography", "no-std"]
readme = "README.md"
edition = "2018"

[dependencies]
crypto-mac = "0.7"
digest = "0.8"
crypto-mac = "= 0.8.0-pre"
digest = "= 0.9.0-pre"

[dev-dependencies]
crypto-mac = { version = "0.7", features = ["dev"] }
md-5 = { version = "0.8", default-features = false }
sha2 = { version = "0.8", default-features = false }
crypto-mac = { version = "0.8.0-pre", features = ["dev"] }
md-5 = { version = "0.9.0-pre", default-features = false }
sha2 = { version = "0.9.0-pre", default-features = false }
76 changes: 38 additions & 38 deletions hmac/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,76 +10,68 @@
//! To get the authentication code:
//!
//! ```rust
//! extern crate hmac;
//! extern crate sha2;
//!
//! use sha2::Sha256;
//! use hmac::{Hmac, Mac};
//! use hmac::{Hmac, Mac, NewMac};
//!
//! // Create alias for HMAC-SHA256
//! type HmacSha256 = Hmac<Sha256>;
//!
//! # fn main() {
//! // Create HMAC-SHA256 instance which implements `Mac` trait
//! let mut mac = HmacSha256::new_varkey(b"my secret and secure key")
//! .expect("HMAC can take key of any size");
//! mac.input(b"input message");
//! mac.update(b"input message");
//!
//! // `result` has type `MacResult` which is a thin wrapper around array of
//! // `result` has type `Output` which is a thin wrapper around array of
//! // bytes for providing constant time equality check
//! let result = mac.result();
//! // To get underlying array use `code` method, but be careful, since
//! // incorrect use of the code value may permit timing attacks which defeat
//! // the security provided by the `MacResult`
//! let code_bytes = result.code();
//! # }
//! // the security provided by the `Output`
//! let code_bytes = result.into_bytes();
//! ```
//!
//! To verify the message:
//!
//! ```rust
//! # extern crate hmac;
//! # extern crate sha2;
//! # use sha2::Sha256;
//! # use hmac::{Hmac, Mac};
//! # fn main() {
//! # use hmac::{Hmac, Mac, NewMac};
//! # type HmacSha256 = Hmac<Sha256>;
//! let mut mac = HmacSha256::new_varkey(b"my secret and secure key")
//! .expect("HMAC can take key of any size");
//!
//! mac.input(b"input message");
//! mac.update(b"input message");
//!
//! # let code_bytes = mac.clone().result().code();
//! # let code_bytes = mac.clone().result().into_bytes();
//! // `verify` will return `Ok(())` if code is correct, `Err(MacError)` otherwise
//! mac.verify(&code_bytes).unwrap();
//! # }
//! ```
//!
//! # Block and input sizes
//! Usually it is assumed that block size is larger than output size, due to the
//! generic nature of the implementation this edge case must be handled as well
//! to remove potential panic scenario. This is done by truncating hash output
//! to the hash block size if needed.

#![no_std]
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
pub extern crate crypto_mac;
pub extern crate digest;

pub use crypto_mac::{self, Mac, NewMac};
pub use digest;

use core::cmp::min;
use core::fmt;
pub use crypto_mac::Mac;
use crypto_mac::{InvalidKeyLength, MacResult};
use crypto_mac::{InvalidKeyLength, Output};
use digest::generic_array::sequence::GenericSequence;
use digest::generic_array::{ArrayLength, GenericArray};
use digest::{BlockInput, FixedOutput, Input, Reset};
use digest::{BlockInput, FixedOutput, Update, Reset};

const IPAD: u8 = 0x36;
const OPAD: u8 = 0x5C;

/// The `Hmac` struct represents an HMAC using a given hash function `D`.
pub struct Hmac<D>
where
D: Input + BlockInput + FixedOutput + Reset + Default + Clone,
D: Update + BlockInput + FixedOutput + Reset + Default + Clone,
D::BlockSize: ArrayLength<u8>,
{
digest: D,
Expand All @@ -89,7 +81,7 @@ where

impl<D> Clone for Hmac<D>
where
D: Input + BlockInput + FixedOutput + Reset + Default + Clone,
D: Update + BlockInput + FixedOutput + Reset + Default + Clone,
D::BlockSize: ArrayLength<u8>,
{
fn clone(&self) -> Hmac<D> {
Expand All @@ -103,10 +95,10 @@ where

impl<D> fmt::Debug for Hmac<D>
where
D: Input + BlockInput + FixedOutput + Reset + Default + Clone + fmt::Debug,
D: Update + BlockInput + FixedOutput + Reset + Default + Clone + fmt::Debug,
D::BlockSize: ArrayLength<u8>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Hmac")
.field("digest", &self.digest)
.field("i_key_pad", &self.i_key_pad)
Expand All @@ -115,13 +107,12 @@ where
}
}

impl<D> Mac for Hmac<D>
impl<D> NewMac for Hmac<D>
where
D: Input + BlockInput + FixedOutput + Reset + Default + Clone,
D: Update + BlockInput + FixedOutput + Reset + Default + Clone,
D::BlockSize: ArrayLength<u8>,
D::OutputSize: ArrayLength<u8>,
{
type OutputSize = D::OutputSize;
type KeySize = D::BlockSize;

fn new(key: &GenericArray<u8, Self::KeySize>) -> Self {
Expand Down Expand Up @@ -150,7 +141,7 @@ where
}
} else {
let mut digest = D::default();
digest.input(key);
digest.update(key);
let output = digest.fixed_result();
// `n` is calculated at compile time and will equal
// D::OutputSize. This is used to ensure panic-free code
Expand All @@ -161,28 +152,37 @@ where
}
}

hmac.digest.input(&hmac.i_key_pad);
hmac.opad_digest.input(&opad);
hmac.digest.update(&hmac.i_key_pad);
hmac.opad_digest.update(&opad);

Ok(hmac)
}
}

impl<D> Mac for Hmac<D>
where
D: Update + BlockInput + FixedOutput + Reset + Default + Clone,
D::BlockSize: ArrayLength<u8>,
D::OutputSize: ArrayLength<u8>,
{
type OutputSize = D::OutputSize;

#[inline]
fn input(&mut self, data: &[u8]) {
self.digest.input(data);
fn update(&mut self, data: &[u8]) {
self.digest.update(data);
}

#[inline]
fn result(self) -> MacResult<D::OutputSize> {
fn result(self) -> Output<Self> {
let mut opad_digest = self.opad_digest.clone();
let hash = self.digest.fixed_result();
opad_digest.input(&hash);
MacResult::new(opad_digest.fixed_result())
opad_digest.update(&hash);
Output::new(opad_digest.fixed_result())
}

#[inline]
fn reset(&mut self) {
self.digest.reset();
self.digest.input(&self.i_key_pad);
self.digest.update(&self.i_key_pad);
}
}
7 changes: 2 additions & 5 deletions hmac/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
//! Test vectors from:
//! - md5: RFC 2104, plus wiki test
//! - sha2: RFC 4231

#![no_std]
#[macro_use]
extern crate crypto_mac;
extern crate hmac;
extern crate md5;
extern crate sha2;

use crypto_mac::new_test;
use hmac::Hmac;

new_test!(hmac_md5, "md5", Hmac<md5::Md5>);
Expand Down