Skip to content

Commit

Permalink
Merge pull request #13 from andrewwhitehead/more-keys
Browse files Browse the repository at this point in the history
0.2.0-pre.6 updates
  • Loading branch information
andrewwhitehead authored Jul 14, 2021
2 parents 999fb09 + f5bdb18 commit deda2a9
Show file tree
Hide file tree
Showing 29 changed files with 438 additions and 371 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["askar-crypto"]

[package]
name = "aries-askar"
version = "0.2.0-pre.5"
version = "0.2.0"
authors = ["Hyperledger Aries Contributors <[email protected]>"]
edition = "2018"
description = "Hyperledger Aries Askar secure storage"
Expand Down Expand Up @@ -67,7 +67,7 @@ uuid = { version = "0.8", features = ["v4"] }
zeroize = "1.3"

[dependencies.askar-crypto]
version = "0.2.0-pre.5"
version = "0.2"
path = "./askar-crypto"
features = ["all_keys", "any_key", "argon2", "crypto_box", "std"]

Expand Down
7 changes: 4 additions & 3 deletions askar-crypto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "askar-crypto"
version = "0.2.0-pre.5"
version = "0.2.0"
authors = ["Hyperledger Aries Contributors <[email protected]>"]
edition = "2018"
description = "Hyperledger Aries Askar cryptography"
Expand All @@ -23,9 +23,10 @@ any_key = ["alloc"]
aes = ["aes-core", "aes-gcm", "block-modes", "hmac"]
bls = ["bls12_381", "hkdf"]
chacha = ["chacha20poly1305"]
crypto_box = ["alloc", "crypto_box_rs", "ed25519"]
crypto_box = ["alloc", "crypto_box_rs", "ed25519", "getrandom"]
ec_curves = ["k256", "p256"]
ed25519 = ["curve25519-dalek", "ed25519-dalek", "x25519-dalek"]
getrandom = ["rand/getrandom"]

[dev-dependencies]
base64 = { version = "0.13", default-features = false, features = ["alloc"] }
Expand Down Expand Up @@ -63,7 +64,7 @@ hkdf = { version = "0.11", optional = true }
hmac = { version = "0.11", optional = true }
k256 = { version = "0.8", default-features = false, features = ["arithmetic", "ecdsa", "ecdh", "sha256", "zeroize"], optional = true }
p256 = { version = "0.8", default-features = false, features = ["arithmetic", "ecdsa", "ecdh", "zeroize"], optional = true }
rand = { version = "0.8", default-features = false, features = ["getrandom"] }
rand = { version = "0.8", default-features = false }
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde-json-core = { version = "0.4", default-features = false }
subtle = "2.4"
Expand Down
155 changes: 95 additions & 60 deletions askar-crypto/benches/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ extern crate criterion;

use askar_crypto::{
alg::{
aes::{A128CbcHs256, A128Gcm, AesKey},
chacha20::{Chacha20Key, C20P},
aes::{A128CbcHs256, A128Gcm, A256CbcHs512, A256Gcm, AesKey},
chacha20::{Chacha20Key, C20P, XC20P},
AnyKey, AnyKeyCreate, Chacha20Types, KeyAlg,
},
buffer::{SecretBytes, WriteBuffer, Writer},
buffer::{SecretBytes, WriteBuffer},
encrypt::{KeyAeadInPlace, KeyAeadMeta},
random::fill_random,
repr::KeyGen,
Expand All @@ -16,67 +16,102 @@ use askar_crypto::{
use criterion::{black_box, Criterion};

fn criterion_benchmark(c: &mut Criterion) {
{
let message = b"test message for encrypting";
const MSG_SIZE: usize = 2000000;
const ALLOC_SIZE: usize = MSG_SIZE + 512;

c.bench_function(&format!("aes128gcm encrypt"), move |b| {
let key = AesKey::<A128Gcm>::generate().unwrap();
let nonce = AesKey::<A128Gcm>::random_nonce();
b.iter(|| {
let mut buffer = [0u8; 255];
buffer[0..message.len()].copy_from_slice(black_box(&message[..]));
let mut writer = Writer::from_slice_position(&mut buffer, message.len());
key.encrypt_in_place(&mut writer, &nonce, &[]).unwrap();
})
});
c.bench_function(&format!("aes128cbc-hs256 encrypt"), move |b| {
let key = AesKey::<A128CbcHs256>::generate().unwrap();
let nonce = AesKey::<A128CbcHs256>::random_nonce();
b.iter(|| {
let mut buffer = [0u8; 255];
buffer[0..message.len()].copy_from_slice(black_box(&message[..]));
let mut writer = Writer::from_slice_position(&mut buffer, message.len());
key.encrypt_in_place(&mut writer, &nonce, &[]).unwrap();
})
});
let mut message = vec![0u8; MSG_SIZE];
fill_random(&mut message[..]);
let message = &message[..];

c.bench_function(&format!("chacha20-poly1305 encrypt"), move |b| {
let key = Chacha20Key::<C20P>::generate().unwrap();
let nonce = Chacha20Key::<C20P>::random_nonce();
b.iter(|| {
let mut buffer = [0u8; 255];
buffer[0..message.len()].copy_from_slice(black_box(&message[..]));
let mut writer = Writer::from_slice_position(&mut buffer, message.len());
key.encrypt_in_place(&mut writer, &nonce, &[]).unwrap();
})
});
c.bench_function(&format!("aes128gcm encrypt"), move |b| {
let key = AesKey::<A128Gcm>::random().unwrap();
let nonce = AesKey::<A128Gcm>::random_nonce();
let mut buffer = Vec::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.extend_from_slice(black_box(&message[..]));
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});
c.bench_function(&format!("aes256gcm encrypt"), move |b| {
let key = AesKey::<A256Gcm>::random().unwrap();
let nonce = AesKey::<A256Gcm>::random_nonce();
let mut buffer = Vec::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.extend_from_slice(black_box(&message[..]));
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});

// test overhead of SecretBytes
c.bench_function(&format!("chacha20-poly1305 encrypt alloc"), move |b| {
let key = Chacha20Key::<C20P>::generate().unwrap();
let nonce = Chacha20Key::<C20P>::random_nonce();
b.iter(|| {
let mut buffer = SecretBytes::with_capacity(255);
buffer.buffer_write(black_box(&message[..])).unwrap();
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});
c.bench_function(&format!("aes128cbc-hs256 encrypt"), move |b| {
let key = AesKey::<A128CbcHs256>::random().unwrap();
let nonce = AesKey::<A128CbcHs256>::random_nonce();
let mut buffer = Vec::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.extend_from_slice(black_box(&message[..]));
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});
c.bench_function(&format!("aes256cbc-hs512 encrypt"), move |b| {
let key = AesKey::<A256CbcHs512>::random().unwrap();
let nonce = AesKey::<A256CbcHs512>::random_nonce();
let mut buffer = Vec::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.extend_from_slice(black_box(&message[..]));
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});

// test overhead of AnyKey
c.bench_function(&format!("chacha20-poly1305 encrypt as any"), move |b| {
let key = Box::<AnyKey>::generate(KeyAlg::Chacha20(Chacha20Types::C20P)).unwrap();
let mut nonce = [0u8; 255];
let nonce_len = key.aead_params().nonce_length;
fill_random(&mut nonce[..nonce_len]);
b.iter(|| {
let mut buffer = [0u8; 255];
buffer[0..message.len()].copy_from_slice(black_box(&message[..]));
let mut writer = Writer::from_slice_position(&mut buffer, message.len());
key.encrypt_in_place(&mut writer, &nonce[..nonce_len], &[])
.unwrap();
})
});
}
c.bench_function(&format!("chacha20-poly1305 encrypt"), move |b| {
let key = Chacha20Key::<C20P>::random().unwrap();
let nonce = Chacha20Key::<C20P>::random_nonce();
let mut buffer = Vec::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.extend_from_slice(black_box(&message[..]));
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});
c.bench_function(&format!("xchacha20-poly1305 encrypt"), move |b| {
let key = Chacha20Key::<XC20P>::random().unwrap();
let nonce = Chacha20Key::<XC20P>::random_nonce();
let mut buffer = Vec::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.extend_from_slice(black_box(&message[..]));
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});

// test overhead of SecretBytes
c.bench_function(&format!("chacha20-poly1305 encrypt alloc"), move |b| {
let key = Chacha20Key::<C20P>::random().unwrap();
let nonce = Chacha20Key::<C20P>::random_nonce();
let mut buffer = SecretBytes::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.buffer_write(black_box(&message[..])).unwrap();
key.encrypt_in_place(&mut buffer, &nonce, &[]).unwrap();
})
});

// test overhead of AnyKey
c.bench_function(&format!("chacha20-poly1305 encrypt as any"), move |b| {
let key = Box::<AnyKey>::random(KeyAlg::Chacha20(Chacha20Types::C20P)).unwrap();
let mut nonce = [0u8; 255];
let nonce_len = key.aead_params().nonce_length;
fill_random(&mut nonce[..nonce_len]);
let mut buffer = Vec::with_capacity(ALLOC_SIZE);
b.iter(|| {
buffer.clear();
buffer.extend_from_slice(black_box(&message[..]));
key.encrypt_in_place(&mut buffer, &nonce[..nonce_len], &[])
.unwrap();
})
});
}

criterion_group!(benches, criterion_benchmark);
Expand Down
25 changes: 12 additions & 13 deletions askar-crypto/src/alg/aes/cbc_hmac.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! AES-CBC-HMAC-SHA2
//! AES-CBC-HMAC
use core::marker::PhantomData;

Expand All @@ -11,6 +11,7 @@ use block_modes::{
};
use digest::{BlockInput, FixedOutput, Reset, Update};
use hmac::{Hmac, Mac, NewMac};
use subtle::ConstantTimeEq;

use super::{AesKey, AesType, NonceSize, TagSize};
use crate::{
Expand All @@ -24,7 +25,7 @@ use crate::{
},
};

/// 128 bit AES-CBC with HMAC-256
/// 128 bit AES-CBC with SHA-256 HMAC
pub type A128CbcHs256 = AesCbcHmac<Aes128, sha2::Sha256>;

impl AesType for A128CbcHs256 {
Expand All @@ -33,7 +34,7 @@ impl AesType for A128CbcHs256 {
const JWK_ALG: &'static str = "A128CBC-HS256";
}

/// 256 bit AES-CBC with HMAC-512
/// 256 bit AES-CBC with SHA-512 HMAC
pub type A256CbcHs512 = AesCbcHmac<Aes256, sha2::Sha512>;

impl AesType for A256CbcHs512 {
Expand Down Expand Up @@ -147,8 +148,7 @@ where
hmac.update(&buffer.as_ref()[..ctext_end]);
hmac.update(&((aad.len() as u64) * 8).to_be_bytes());
let mac = hmac.finalize().into_bytes();
let tag_match =
subtle::ConstantTimeEq::ct_eq(tag.as_ref(), &mac[..TagSize::<Self>::USIZE]).unwrap_u8();
let tag_match = tag.as_ref().ct_eq(&mac[..TagSize::<Self>::USIZE]);

let enc_key = GenericArray::from_slice(&self.0[C::KeySize::USIZE..]);
let dec_len = Cbc::<C, Pkcs7>::new_fix(enc_key, GenericArray::from_slice(nonce))
Expand All @@ -157,7 +157,7 @@ where
.len();
buffer.buffer_resize(dec_len)?;

if tag_match != 1 {
if tag_match.unwrap_u8() != 1 {
Err(err_msg!(Encryption, "AEAD decryption error"))
} else {
Ok(())
Expand All @@ -184,7 +184,7 @@ mod tests {
use std::string::ToString;

#[test]
fn encrypt_expected_cbc_hmac_128() {
fn encrypt_expected_cbc_128_hmac_256() {
let key_data = &hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
let input = b"A cipher system must not be required to be secret, and it must be able to fall into the hands of the enemy without inconvenience";
let nonce = &hex!("1af38c2dc2b96ffdd86694092341bc04");
Expand All @@ -200,16 +200,15 @@ mod tests {
a94ac9b47ad2655c5f10f9aef71427e2fc6f9b3f399a221489f16362c7032336\
09d45ac69864e3321cf82935ac4096c86e133314c54019e8ca7980dfa4b9cf1b\
384c486f3a54c51078158ee5d79de59fbd34d848b3d69550a67646344427ade5\
4b8851ffb598f7f80074b9473c82e2db\
652c3fa36b0a7c5b3219fab3a30bc1c4"
4b8851ffb598f7f80074b9473c82e2db652c3fa36b0a7c5b3219fab3a30bc1c4"
);
key.decrypt_in_place(&mut buffer, &nonce[..], &aad[..])
.unwrap();
assert_eq!(buffer, &input[..]);
}

#[test]
fn encrypt_expected_cbc_hmac_256() {
fn encrypt_expected_cbc_256_hmac_512() {
let key_data = &hex!(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"
Expand All @@ -228,16 +227,16 @@ mod tests {
822c301dd67c373bccb584ad3e9279c2e6d12a1374b77f077553df829410446b\
36ebd97066296ae6427ea75c2e0846a11a09ccf5370dc80bfecbad28c73f09b3\
a3b75e662a2594410ae496b2e2e6609e31e6e02cc837f053d21f37ff4f51950b\
be2638d09dd7a4930930806d0703b1f6\
4dd3b4c088a7f45c216839645b2012bf2e6269a8c56a816dbc1b267761955bc5"
be2638d09dd7a4930930806d0703b1f64dd3b4c088a7f45c216839645b2012bf\
2e6269a8c56a816dbc1b267761955bc5"
);
key.decrypt_in_place(&mut buffer, &nonce[..], &aad[..])
.unwrap();
assert_eq!(buffer, &input[..]);
}

#[test]
fn encrypt_expected_cbc_hmac_1pu() {
fn encrypt_expected_ecdh_1pu_cbc_hmac() {
let key_data = &hex!(
"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0
dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0"
Expand Down
29 changes: 7 additions & 22 deletions askar-crypto/src/alg/aes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use crate::{
generic_array::{typenum::Unsigned, GenericArray},
jwk::{JwkEncoder, ToJwk},
kdf::{FromKeyDerivation, FromKeyExchange, KeyDerivation, KeyExchange},
random::fill_random_deterministic,
repr::{KeyGen, KeyMeta, KeySecretBytes, Seed, SeedMethod},
random::KeyMaterial,
repr::{KeyGen, KeyMeta, KeySecretBytes},
};

mod cbc_hmac;
Expand Down Expand Up @@ -91,23 +91,8 @@ impl<T: AesType> KeyMeta for AesKey<T> {
}

impl<T: AesType> KeyGen for AesKey<T> {
fn generate() -> Result<Self, Error> {
Ok(AesKey(KeyType::<T>::random()))
}

fn from_seed(seed: Seed<'_>) -> Result<Self, Error>
where
Self: Sized,
{
match seed {
Seed::Bytes(ikm, SeedMethod::Preferred) | Seed::Bytes(ikm, SeedMethod::RandomDet) => {
Ok(Self(KeyType::<T>::try_new_with(|arr| {
fill_random_deterministic(ikm, arr)
})?))
}
#[allow(unreachable_patterns)]
_ => Err(err_msg!(Unsupported)),
}
fn generate(rng: impl KeyMaterial) -> Result<Self, Error> {
Ok(AesKey(KeyType::<T>::generate(rng)))
}
}

Expand Down Expand Up @@ -270,7 +255,7 @@ mod tests {
{
let input = b"hello";
let aad = b"additional data";
let key = AesKey::<T>::generate().unwrap();
let key = AesKey::<T>::random().unwrap();
let mut buffer = SecretBytes::from_slice(input);
let params = key.aead_params();
let pad_len = key.aead_padding(input.len());
Expand All @@ -295,7 +280,7 @@ mod tests {

#[test]
fn test_random() {
let key = AesKey::<A128CbcHs256>::generate().unwrap();
let key = AesKey::<A128CbcHs256>::random().unwrap();
let nonce = AesKey::<A128CbcHs256>::random_nonce();
let message = b"hello there";
let mut buffer = [0u8; 255];
Expand All @@ -307,7 +292,7 @@ mod tests {
#[test]
fn serialize_round_trip() {
fn test_serialize<T: AesType>() {
let key = AesKey::<T>::generate().unwrap();
let key = AesKey::<T>::random().unwrap();
let sk = key.to_secret_bytes().unwrap();
let bytes = serde_cbor::to_vec(&key).unwrap();
let deser: &[u8] = serde_cbor::from_slice(bytes.as_ref()).unwrap();
Expand Down
Loading

0 comments on commit deda2a9

Please sign in to comment.