Update hmac and blake3 (#673)

* Update hmac and blake3

* Remain paranoid for `0.*` crates

* Most paranoid versions :)

* Updated aes and using published version of blake3

Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
This commit is contained in:
Drazen Urch
2021-09-21 10:59:17 +02:00
committed by GitHub
parent 5b03982043
commit 5dfaff6296
13 changed files with 261 additions and 321 deletions
Generated
+203 -267
View File
File diff suppressed because it is too large Load Diff
@@ -18,7 +18,7 @@ pub enum ReplyKeyStorageError {
/// Permanent storage for keys in all sent [`ReplySURB`]
///
/// Each sent out [`ReplySURB`] has a new key associated with it that is going to be used for
/// payload encryption. In order to decrypt whatever reply we receive, we need to know which
/// payload encryption. In order to -decrypt whatever reply we receive, we need to know which
/// key to use for that purpose. We do it based on received `H(t)` which has to be included
/// with each reply.
/// Moreover, there is no restriction when the [`ReplySURB`] might get used so we need to
+7 -8
View File
@@ -7,15 +7,14 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
aes-ctr = "0.6.0"
bs58 = "0.4"
blake3 = "0.3"
#blake3 = { version = "0.3", features = ["traits-preview"]}
digest = "0.9"
aes = { version = "0.7.4", features = ["ctr"] }
bs58 = "0.4.0"
blake3 = { version = "1.0.0", features = ["traits-preview"] }
digest = "0.9.0"
generic-array = "0.14"
hkdf = "0.10"
hmac = "0.8"
cipher = "0.2"
hkdf = "0.11.0"
hmac = "0.11.0"
cipher = "0.3.0"
x25519-dalek = "1.1"
ed25519-dalek = "1.0"
log = "0.4"
+2 -2
View File
@@ -18,7 +18,7 @@ where
D::OutputSize: ArrayLength<u8>,
{
let mut hmac =
Hmac::<D>::new_varkey(key).expect("HMAC should be able to take key of any size!");
Hmac::<D>::new_from_slice(key).expect("HMAC should be able to take key of any size!");
hmac.update(data);
hmac.finalize()
}
@@ -31,7 +31,7 @@ where
D::OutputSize: ArrayLength<u8>,
{
let mut hmac =
Hmac::<D>::new_varkey(key).expect("HMAC should be able to take key of any size!");
Hmac::<D>::new_from_slice(key).expect("HMAC should be able to take key of any size!");
hmac.update(data);
// note, under the hood ct_eq is called
hmac.verify(tag).is_ok()
+1 -1
View File
@@ -13,7 +13,7 @@ pub use generic_array;
// with the below my idea was to try to introduce having a single place of importing all hashing, encryption,
// etc. algorithms and import them elsewhere as needed via common/crypto
pub use aes_ctr;
pub use aes;
pub use blake3;
// TODO: this function uses all three modules: asymmetric crypto, symmetric crypto and derives key...,
+7 -7
View File
@@ -3,7 +3,7 @@
use crate::asymmetric::encryption;
use crate::hkdf;
use cipher::stream::{Key, NewStreamCipher, SyncStreamCipher};
use cipher::{CipherKey, NewCipher, StreamCipher};
use digest::{BlockInput, FixedOutput, Reset, Update};
use generic_array::{typenum::Unsigned, ArrayLength};
use rand::{CryptoRng, RngCore};
@@ -13,9 +13,9 @@ use rand::{CryptoRng, RngCore};
pub fn new_ephemeral_shared_key<C, D, R>(
rng: &mut R,
remote_key: &encryption::PublicKey,
) -> (encryption::KeyPair, Key<C>)
) -> (encryption::KeyPair, CipherKey<C>)
where
C: SyncStreamCipher + NewStreamCipher,
C: StreamCipher + NewCipher,
D: Update + BlockInput + FixedOutput + Reset + Default + Clone,
D::BlockSize: ArrayLength<u8>,
D::OutputSize: ArrayLength<u8>,
@@ -31,7 +31,7 @@ where
.expect("somehow too long okm was provided");
let derived_shared_key =
Key::<C>::from_exact_iter(okm).expect("okm was expanded to incorrect length!");
CipherKey::<C>::from_exact_iter(okm).expect("okm was expanded to incorrect length!");
(ephemeral_keypair, derived_shared_key)
}
@@ -40,9 +40,9 @@ where
pub fn recompute_shared_key<C, D>(
remote_key: &encryption::PublicKey,
local_key: &encryption::PrivateKey,
) -> Key<C>
) -> CipherKey<C>
where
C: SyncStreamCipher + NewStreamCipher,
C: StreamCipher + NewCipher,
D: Update + BlockInput + FixedOutput + Reset + Default + Clone,
D::BlockSize: ArrayLength<u8>,
D::OutputSize: ArrayLength<u8>,
@@ -53,5 +53,5 @@ where
let okm = hkdf::extract_then_expand::<D>(None, &dh_result, None, C::KeySize::to_usize())
.expect("somehow too long okm was provided");
Key::<C>::from_exact_iter(okm).expect("okm was expanded to incorrect length!")
CipherKey::<C>::from_exact_iter(okm).expect("okm was expanded to incorrect length!")
}
+23 -18
View File
@@ -1,13 +1,14 @@
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use cipher::stream::{Nonce, StreamCipher, SyncStreamCipher};
use cipher::{Nonce, StreamCipher};
use generic_array::{typenum::Unsigned, GenericArray};
use rand::{CryptoRng, RngCore};
// re-export this for ease of use
pub use cipher::stream::{Key, NewStreamCipher};
pub use cipher::{CipherKey, NewCipher};
// SECURITY:
// TODO: note that this is not the most secure approach here
// we are not using nonces properly but instead "kinda" thinking of them as IVs.
// Nonce require, as the name suggest, being only seen once. Ever.
@@ -20,9 +21,9 @@ pub use cipher::stream::{Key, NewStreamCipher};
#[allow(clippy::upper_case_acronyms)]
pub type IV<C> = Nonce<C>;
pub fn generate_key<C, R>(rng: &mut R) -> Key<C>
pub fn generate_key<C, R>(rng: &mut R) -> CipherKey<C>
where
C: NewStreamCipher,
C: NewCipher,
R: RngCore + CryptoRng,
{
let mut key = GenericArray::default();
@@ -32,7 +33,7 @@ where
pub fn random_iv<C, R>(rng: &mut R) -> IV<C>
where
C: NewStreamCipher,
C: NewCipher,
R: RngCore + CryptoRng,
{
let mut iv = GenericArray::default();
@@ -42,14 +43,14 @@ where
pub fn zero_iv<C>() -> IV<C>
where
C: NewStreamCipher,
C: NewCipher,
{
GenericArray::default()
}
pub fn iv_from_slice<C>(b: &[u8]) -> &IV<C>
where
C: NewStreamCipher,
C: NewCipher,
{
if b.len() != C::NonceSize::to_usize() {
// `from_slice` would have caused a panic about this issue anyway.
@@ -66,38 +67,42 @@ where
// TODO: there's really no way to use more parts of the keystream if it was required at some point.
// However, do we really expect to ever need it?
pub fn encrypt<C>(key: &Key<C>, iv: &IV<C>, data: &[u8]) -> Vec<u8>
#[inline]
pub fn encrypt<C>(key: &CipherKey<C>, iv: &IV<C>, data: &[u8]) -> Vec<u8>
where
C: SyncStreamCipher + NewStreamCipher,
C: StreamCipher + NewCipher,
{
let mut ciphertext = data.to_vec();
encrypt_in_place::<C>(key, iv, &mut ciphertext);
ciphertext
}
pub fn encrypt_in_place<C>(key: &Key<C>, iv: &IV<C>, data: &mut [u8])
#[inline]
pub fn encrypt_in_place<C>(key: &CipherKey<C>, iv: &IV<C>, data: &mut [u8])
where
C: SyncStreamCipher + NewStreamCipher,
C: StreamCipher + NewCipher,
{
let mut cipher = C::new(key, iv);
cipher.encrypt(data)
cipher.apply_keystream(data)
}
pub fn decrypt<C>(key: &Key<C>, iv: &IV<C>, ciphertext: &[u8]) -> Vec<u8>
#[inline]
pub fn decrypt<C>(key: &CipherKey<C>, iv: &IV<C>, ciphertext: &[u8]) -> Vec<u8>
where
C: SyncStreamCipher + NewStreamCipher,
C: StreamCipher + NewCipher,
{
let mut data = ciphertext.to_vec();
decrypt_in_place::<C>(key, iv, &mut data);
data
}
pub fn decrypt_in_place<C>(key: &Key<C>, iv: &IV<C>, data: &mut [u8])
#[inline]
pub fn decrypt_in_place<C>(key: &CipherKey<C>, iv: &IV<C>, data: &mut [u8])
where
C: SyncStreamCipher + NewStreamCipher,
C: StreamCipher + NewCipher,
{
let mut cipher = C::new(key, iv);
cipher.decrypt(data)
cipher.apply_keystream(data)
}
#[cfg(test)]
@@ -108,7 +113,7 @@ mod tests {
#[cfg(test)]
mod aes_ctr128 {
use super::*;
use aes_ctr::Aes128Ctr;
use aes::Aes128Ctr;
#[test]
fn zero_iv_is_actually_zero() {
@@ -3,7 +3,7 @@
use crate::AckKey;
use crypto::generic_array::typenum::Unsigned;
use crypto::symmetric::stream_cipher::{self, encrypt, iv_from_slice, random_iv, NewStreamCipher};
use crypto::symmetric::stream_cipher::{self, encrypt, iv_from_slice, random_iv, NewCipher};
use nymsphinx_params::{
packet_sizes::PacketSize, AckEncryptionAlgorithm, SerializedFragmentIdentifier, FRAG_ID_LEN,
};
@@ -33,7 +33,7 @@ pub fn recover_identifier(
return None;
}
let iv_size = <AckEncryptionAlgorithm as NewStreamCipher>::NonceSize::to_usize();
let iv_size = <AckEncryptionAlgorithm as NewCipher>::NonceSize::to_usize();
let iv = iv_from_slice::<AckEncryptionAlgorithm>(&iv_id_ciphertext[..iv_size]);
let id = stream_cipher::decrypt::<AckEncryptionAlgorithm>(
+4 -4
View File
@@ -2,13 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
use crypto::generic_array::{typenum::Unsigned, GenericArray};
use crypto::symmetric::stream_cipher::{generate_key, Key, NewStreamCipher};
use crypto::symmetric::stream_cipher::{generate_key, CipherKey, NewCipher};
use nymsphinx_params::AckEncryptionAlgorithm;
use pemstore::traits::PemStorableKey;
use rand::{CryptoRng, RngCore};
use std::fmt::{self, Display, Formatter};
pub struct AckKey(Key<AckEncryptionAlgorithm>);
pub struct AckKey(CipherKey<AckEncryptionAlgorithm>);
#[derive(Debug)]
pub enum AckKeyConversionError {
@@ -33,7 +33,7 @@ impl AckKey {
}
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, AckKeyConversionError> {
if bytes.len() != <AckEncryptionAlgorithm as NewStreamCipher>::KeySize::to_usize() {
if bytes.len() != <AckEncryptionAlgorithm as NewCipher>::KeySize::to_usize() {
return Err(AckKeyConversionError::BytesOfInvalidLengthError);
}
@@ -48,7 +48,7 @@ impl AckKey {
self.0.as_ref()
}
pub fn inner(&self) -> &Key<AckEncryptionAlgorithm> {
pub fn inner(&self) -> &CipherKey<AckEncryptionAlgorithm> {
&self.0
}
}
@@ -5,7 +5,7 @@ pub use crypto::generic_array::typenum::Unsigned;
use crypto::{
crypto_hash,
generic_array::GenericArray,
symmetric::stream_cipher::{generate_key, Key, NewStreamCipher},
symmetric::stream_cipher::{generate_key, CipherKey, NewCipher},
Digest,
};
use nymsphinx_params::{ReplySurbEncryptionAlgorithm, ReplySurbKeyDigestAlgorithm};
@@ -15,10 +15,10 @@ use std::fmt::{self, Display, Formatter};
pub type EncryptionKeyDigest =
GenericArray<u8, <ReplySurbKeyDigestAlgorithm as Digest>::OutputSize>;
pub type SurbEncryptionKeySize = <ReplySurbEncryptionAlgorithm as NewStreamCipher>::KeySize;
pub type SurbEncryptionKeySize = <ReplySurbEncryptionAlgorithm as NewCipher>::KeySize;
#[derive(Clone, Debug)]
pub struct SurbEncryptionKey(Key<ReplySurbEncryptionAlgorithm>);
pub struct SurbEncryptionKey(CipherKey<ReplySurbEncryptionAlgorithm>);
#[derive(Debug)]
pub enum SurbEncryptionKeyError {
@@ -64,7 +64,7 @@ impl SurbEncryptionKey {
self.0.as_ref()
}
pub fn inner(&self) -> &Key<ReplySurbEncryptionAlgorithm> {
pub fn inner(&self) -> &CipherKey<ReplySurbEncryptionAlgorithm> {
&self.0
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crypto::aes_ctr::Aes128Ctr;
use crypto::aes::Aes128Ctr;
use crypto::blake3;
// Re-export for ease of use
+2 -2
View File
@@ -2,11 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
use crypto::generic_array::{typenum::Unsigned, GenericArray};
use crypto::symmetric::stream_cipher::{random_iv, NewStreamCipher, IV as CryptoIV};
use crypto::symmetric::stream_cipher::{random_iv, NewCipher, IV as CryptoIV};
use nymsphinx::params::GatewayEncryptionAlgorithm;
use rand::{CryptoRng, RngCore};
type NonceSize = <GatewayEncryptionAlgorithm as NewStreamCipher>::NonceSize;
type NonceSize = <GatewayEncryptionAlgorithm as NewCipher>::NonceSize;
// I think 'IV' looks better than 'Iv', feel free to change that.
#[allow(clippy::upper_case_acronyms)]
@@ -7,7 +7,7 @@ use crypto::generic_array::{
GenericArray,
};
use crypto::hmac::{compute_keyed_hmac, recompute_keyed_hmac_and_verify_tag};
use crypto::symmetric::stream_cipher::{self, Key, NewStreamCipher, IV};
use crypto::symmetric::stream_cipher::{self, CipherKey, NewCipher, IV};
use nymsphinx::params::{GatewayEncryptionAlgorithm, GatewayIntegrityHmacAlgorithm};
use pemstore::traits::PemStorableKey;
use std::fmt::{self, Display, Formatter};
@@ -17,14 +17,14 @@ pub type SharedKeySize = Sum<EncryptionKeySize, MacKeySize>;
// we're using 16 byte long key in sphinx, so let's use the same one here
type MacKeySize = U16;
type EncryptionKeySize = <GatewayEncryptionAlgorithm as NewStreamCipher>::KeySize;
type EncryptionKeySize = <GatewayEncryptionAlgorithm as NewCipher>::KeySize;
/// Shared key used when computing MAC for messages exchanged between client and its gateway.
pub type MacKey = GenericArray<u8, MacKeySize>;
#[derive(Clone, Debug)]
pub struct SharedKeys {
encryption_key: Key<GatewayEncryptionAlgorithm>,
encryption_key: CipherKey<GatewayEncryptionAlgorithm>,
mac_key: MacKey,
}
@@ -138,7 +138,7 @@ impl SharedKeys {
Ok(message_bytes_mut.to_vec())
}
pub fn encryption_key(&self) -> &Key<GatewayEncryptionAlgorithm> {
pub fn encryption_key(&self) -> &CipherKey<GatewayEncryptionAlgorithm> {
&self.encryption_key
}