summaryrefslogtreecommitdiffstats
path: root/vendor/hmac/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/hmac/src/lib.rs')
-rw-r--r--vendor/hmac/src/lib.rs131
1 files changed, 131 insertions, 0 deletions
diff --git a/vendor/hmac/src/lib.rs b/vendor/hmac/src/lib.rs
new file mode 100644
index 0000000..e79c068
--- /dev/null
+++ b/vendor/hmac/src/lib.rs
@@ -0,0 +1,131 @@
+//! Generic implementation of Hash-based Message Authentication Code (HMAC).
+//!
+//! To use it you will need a cryptographic hash function implementation which
+//! implements the [`digest`] crate traits. You can find compatible crates
+//! (e.g. [`sha2`]) in the [`RustCrypto/hashes`] repository.
+//!
+//! This crate provides two HMAC implementation [`Hmac`] and [`SimpleHmac`].
+//! The first one is a buffered wrapper around block-level [`HmacCore`].
+//! Internally it uses efficient state representation, but works only with
+//! hash functions which expose block-level API and consume blocks eagerly
+//! (e.g. it will not work with the BLAKE2 family of hash functions).
+//! On the other hand, [`SimpleHmac`] is a bit less efficient memory-wise,
+//! but works with all hash functions which implement the [`Digest`] trait.
+//!
+//! # Examples
+//! Let us demonstrate how to use HMAC using the SHA-256 hash function.
+//!
+//! In the following examples [`Hmac`] is interchangeable with [`SimpleHmac`].
+//!
+//! To get authentication code:
+//!
+//! ```rust
+//! use sha2::Sha256;
+//! use hmac::{Hmac, Mac};
+//! use hex_literal::hex;
+//!
+//! // Create alias for HMAC-SHA256
+//! type HmacSha256 = Hmac<Sha256>;
+//!
+//! let mut mac = HmacSha256::new_from_slice(b"my secret and secure key")
+//! .expect("HMAC can take key of any size");
+//! mac.update(b"input message");
+//!
+//! // `result` has type `CtOutput` which is a thin wrapper around array of
+//! // bytes for providing constant time equality check
+//! let result = mac.finalize();
+//! // To get underlying array use `into_bytes`, but be careful, since
+//! // incorrect use of the code value may permit timing attacks which defeats
+//! // the security provided by the `CtOutput`
+//! let code_bytes = result.into_bytes();
+//! let expected = hex!("
+//! 97d2a569059bbcd8ead4444ff99071f4
+//! c01d005bcefe0d3567e1be628e5fdcd9
+//! ");
+//! assert_eq!(code_bytes[..], expected[..]);
+//! ```
+//!
+//! To verify the message:
+//!
+//! ```rust
+//! # use sha2::Sha256;
+//! # use hmac::{Hmac, Mac};
+//! # use hex_literal::hex;
+//! # type HmacSha256 = Hmac<Sha256>;
+//! let mut mac = HmacSha256::new_from_slice(b"my secret and secure key")
+//! .expect("HMAC can take key of any size");
+//!
+//! mac.update(b"input message");
+//!
+//! let code_bytes = hex!("
+//! 97d2a569059bbcd8ead4444ff99071f4
+//! c01d005bcefe0d3567e1be628e5fdcd9
+//! ");
+//! // `verify_slice` will return `Ok(())` if code is correct, `Err(MacError)` otherwise
+//! mac.verify_slice(&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. This is done by truncating hash output to the hash
+//! block size if needed.
+//!
+//! [`digest`]: https://docs.rs/digest
+//! [`sha2`]: https://docs.rs/sha2
+//! [`RustCrypto/hashes`]: https://github.com/RustCrypto/hashes
+
+#![no_std]
+#![doc(
+ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
+ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
+ html_root_url = "https://docs.rs/hmac/0.12.1"
+)]
+#![forbid(unsafe_code)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![warn(missing_docs, rust_2018_idioms)]
+
+#[cfg(feature = "std")]
+extern crate std;
+
+pub use digest;
+pub use digest::Mac;
+
+use digest::{
+ core_api::{Block, BlockSizeUser},
+ Digest,
+};
+
+mod optim;
+mod simple;
+
+pub use optim::{Hmac, HmacCore};
+pub use simple::SimpleHmac;
+
+const IPAD: u8 = 0x36;
+const OPAD: u8 = 0x5C;
+
+fn get_der_key<D: Digest + BlockSizeUser>(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 zeros. If its larger, we hash it and then pad it
+ // with zeros.
+ if key.len() <= der_key.len() {
+ der_key[..key.len()].copy_from_slice(key);
+ } else {
+ 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 calcualted at compile time, so this
+ // branch gets removed from the 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
+}