diff --git a/common/crypto/src/hkdf.rs b/common/crypto/src/hkdf.rs index 5fe7f56137..bc65831d5d 100644 --- a/common/crypto/src/hkdf.rs +++ b/common/crypto/src/hkdf.rs @@ -3,8 +3,12 @@ use hkdf::{hmac::digest::Digest, Hkdf}; +pub use hkdf::HmacImpl; + +// pub struct Hkdf = Hmac> { + /// Perform HKDF `extract` then `expand` as a single step. -pub fn extract_then_expand( +pub fn extract_then_expand( salt: Option<&[u8]>, ikm: &[u8], info: Option<&[u8]>, @@ -12,11 +16,12 @@ pub fn extract_then_expand( ) -> Result, hkdf::InvalidLength> where D: Digest, + I: HmacImpl, { // TODO: this would need to change if we ever needed the generated pseudorandom key, but // realistically I don't see any reasons why we might need it - let hkdf = Hkdf::::new(salt, ikm); + let hkdf = Hkdf::::new(salt, ikm); let mut okm = vec![0u8; okm_length]; hkdf.expand(info.unwrap_or(&[]), &mut okm)?; diff --git a/common/crypto/src/hmac.rs b/common/crypto/src/hmac.rs index b8dbad43e2..a997b56359 100644 --- a/common/crypto/src/hmac.rs +++ b/common/crypto/src/hmac.rs @@ -2,14 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 use hmac::{ - digest::{crypto_common::BlockSizeUser, Digest, Output}, + digest::{crypto_common::BlockSizeUser, CtOutput, Digest, Output}, Mac, SimpleHmac, }; pub use hmac; // TODO: We should probably change it to use some sealed trait to allow for both `Hmac` and `SimpleHmac` -pub type HmacOutput = Output>; +pub type HmacOutput = CtOutput>; /// Compute keyed hmac pub fn compute_keyed_hmac(key: &[u8], data: &[u8]) -> HmacOutput @@ -25,29 +25,29 @@ where /// Compute keyed hmac and performs constant time equality check with the provided tag value. pub fn recompute_keyed_hmac_and_verify_tag(key: &[u8], data: &[u8], tag: &[u8]) -> bool where - D: Digest, + D: Digest + BlockSizeUser, { let mut hmac = SimpleHmac::::new_from_slice(key) .expect("HMAC was instantiated with a key of an invalid size!"); hmac.update(data); + + let tag_arr = Output::::from_slice(tag); // note, under the hood ct_eq is called - hmac.verify(tag).is_ok() + hmac.verify(tag_arr).is_ok() } -// /// Verifies tag of an hmac output. -// pub fn verify_tag(tag: &[u8], out: HmacOutput) -> bool -// where -// D: Digest, -// { -// if tag.len() != D::output_size() { -// return false; -// } -// -// let tag_bytes = GenericArray::clone_from_slice(tag); -// -// // note, under the hood ct_eq is called -// out == tag_out -// } +/// Verifies tag of an hmac output. +pub fn verify_tag(tag: &[u8], out: HmacOutput) -> bool +where + D: Digest + BlockSizeUser, +{ + if tag.len() != ::output_size() { + return false; + } + + let tag_arr = Output::::from_slice(tag); + out == tag_arr.into() +} #[cfg(test)] mod tests { @@ -71,9 +71,9 @@ mod tests { &output_tag )); - // assert!(verify_tag::( - // &output_tag, - // compute_keyed_hmac::(&key, msg) - // )); + assert!(verify_tag::( + &output_tag, + compute_keyed_hmac::(&key, msg) + )); } } diff --git a/common/crypto/src/shared_key.rs b/common/crypto/src/shared_key.rs index ac4001b957..5ef65b95af 100644 --- a/common/crypto/src/shared_key.rs +++ b/common/crypto/src/shared_key.rs @@ -2,20 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 use crate::asymmetric::encryption; -use crate::hkdf; +use crate::hkdf::{self, HmacImpl}; use cipher::{Key, KeyIvInit, StreamCipher}; use digest::Digest; use rand::{CryptoRng, RngCore}; /// Generate an ephemeral encryption keypair and perform diffie-hellman to establish /// shared key with the remote. -pub fn new_ephemeral_shared_key( +pub fn new_ephemeral_shared_key( rng: &mut R, remote_key: &encryption::PublicKey, ) -> (encryption::KeyPair, Key) where C: StreamCipher + KeyIvInit, D: Digest, + I: HmacImpl, R: RngCore + CryptoRng, { let ephemeral_keypair = encryption::KeyPair::new(rng); @@ -24,7 +25,7 @@ where let dh_result = ephemeral_keypair.private_key().diffie_hellman(remote_key); // there is no reason for this to fail as our okm is expected to be only C::KeySize bytes - let okm = hkdf::extract_then_expand::(None, &dh_result, None, C::KeySize::to_usize()) + let okm = hkdf::extract_then_expand::(None, &dh_result, None, C::key_size()) .expect("somehow too long okm was provided"); let derived_shared_key = @@ -34,18 +35,19 @@ where } /// Recompute shared key using remote public key and local private key. -pub fn recompute_shared_key( +pub fn recompute_shared_key( remote_key: &encryption::PublicKey, local_key: &encryption::PrivateKey, ) -> Key where C: StreamCipher + KeyIvInit, D: Digest, + I: HmacImpl, { let dh_result = local_key.diffie_hellman(remote_key); // there is no reason for this to fail as our okm is expected to be only C::KeySize bytes - let okm = hkdf::extract_then_expand::(None, &dh_result, None, C::KeySize::to_usize()) + let okm = hkdf::extract_then_expand::(None, &dh_result, None, C::key_size()) .expect("somehow too long okm was provided"); Key::::from_exact_iter(okm).expect("okm was expanded to incorrect length!") diff --git a/common/crypto/src/symmetric/stream_cipher.rs b/common/crypto/src/symmetric/stream_cipher.rs index fa6cd1852f..308a610891 100644 --- a/common/crypto/src/symmetric/stream_cipher.rs +++ b/common/crypto/src/symmetric/stream_cipher.rs @@ -1,8 +1,7 @@ // Copyright 2020 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use cipher::{Iv, KeyIvInit, StreamCipher}; -use generic_array::{typenum::Unsigned, GenericArray}; +use cipher::{generic_array::GenericArray, Iv, KeyIvInit, StreamCipher}; use rand::{CryptoRng, RngCore}; // re-export this for ease of use @@ -52,13 +51,13 @@ pub fn iv_from_slice(b: &[u8]) -> &IV where C: KeyIvInit, { - if b.len() != C::NonceSize::to_usize() { + if b.len() != C::iv_size() { // `from_slice` would have caused a panic about this issue anyway. // Now we at least have slightly more information panic!( "Tried to convert {} bytes to IV. Expected {}", b.len(), - C::NonceSize::to_usize() + C::iv_size() ) } GenericArray::from_slice(b)