Fix no_std support (#229)

This commit is contained in:
daxpedda
2021-08-16 20:11:53 -07:00
committed by GitHub
parent 8a7bcf9097
commit 6c7840514d
15 changed files with 179 additions and 208 deletions
+6 -1
View File
@@ -145,15 +145,20 @@ jobs:
target:
# for wasm
- wasm32-unknown-unknown
# for any no_std target
- thumbv6m-none-eabi
backend_feature:
- u64_backend
- u32_backend
- p256,u64_backend
frontend_feature:
- slow-hash
- serialize
steps:
- uses: actions/checkout@v2
- uses: hecrj/setup-rust-action@v1
- run: rustup target add ${{ matrix.target }}
- run: cargo build --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.backend_feature }}
- run: cargo build --verbose --target=${{ matrix.target }} --no-default-features --features ${{ matrix.frontend_feature }} --features ${{ matrix.backend_feature }}
benches:
name: cargo bench compilation
+16 -13
View File
@@ -9,6 +9,7 @@ authors = ["Kevin Lewi <[email protected]>", "François Garillot <[email protected]>"]
license = "MIT"
edition = "2018"
readme = "README.md"
resolver = "2"
[features]
default = ["u64_backend", "serialize"]
@@ -17,32 +18,33 @@ p256 = ["num-bigint", "num-integer", "num-traits", "once_cell", "p256_"]
bench = []
u64_backend = ["curve25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"]
std = ["curve25519-dalek/std"]
std = ["curve25519-dalek/std", "getrandom", "rand/std", "rand/std_rng", "num-bigint/std", "num-integer/std", "num-traits/std"]
serialize = ["serde", "base64", "generic-array/serde", "curve25519-dalek/serde"]
[dependencies]
argon2 = { version = "0.2", optional = true }
base64 = { version = "0.13", optional = true }
argon2 = { version = "0.2", default-features = false, optional = true }
base64 = { version = "0.13", default-features = false, features = ["alloc"], optional = true }
constant_time_eq = "0.1"
curve25519-dalek = { version = "3", default-features = false }
digest = "0.9"
displaydoc = "0.2"
displaydoc = { version = "0.2", default-features = false }
generic-array = "0.14"
generic-bytes = { version = "0.1" }
getrandom = { version = "0.2", features = ["js"] }
getrandom = { version = "0.2", optional = true }
hkdf = "0.11"
hmac = "0.11"
num-bigint = { version = "0.4", optional = true }
num-integer = { version = "0.1", optional = true }
num-traits = { version = "0.2", optional = true }
once_cell = { version = "1", optional = true }
p256_ = { package = "p256", version = "0.9", optional = true }
num-bigint = { version = "0.4", default-features = false, optional = true }
num-integer = { version = "0.1", default-features = false, optional = true }
num-traits = { version = "0.2", default-features = false, optional = true }
once_cell = { version = "1", default-features = false, optional = true }
p256_ = { package = "p256", version = "0.9", default-features = false, features = ["arithmetic", "zeroize"], optional = true }
rand = { version = "0.8", default-features = false }
serde = { version = "1", features = ["derive"], optional = true }
serde = { version = "1", default-features = false, features = ["alloc", "derive"], optional = true }
subtle = { version = "2.3", default-features = false }
thiserror = "1"
zeroize = { version = "1", features = ["zeroize_derive"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"], optional = true }
[dev-dependencies]
base64 = "0.13"
bincode = "1"
@@ -50,6 +52,7 @@ chacha20poly1305 = "0.8"
criterion = "0.3"
hex = "0.4"
lazy_static = "1"
opaque-ke = { path = "", default-features = false, features = ["std"] }
serde_json = "1"
sha2 = "0.9"
proptest = "1"
+7 -8
View File
@@ -8,7 +8,7 @@ use crate::{
errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError},
group::Group,
hash::Hash,
keypair::{KeyPair, PrivateKey, PublicKey},
keypair::{KeyPair, PublicKey},
opaque::{bytestrings_from_identifiers, Identifiers},
};
use alloc::vec;
@@ -16,7 +16,6 @@ use alloc::vec::Vec;
use core::convert::TryFrom;
use digest::Digest;
use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes;
use hkdf::Hkdf;
use hmac::{Hmac, Mac, NewMac};
use rand::{CryptoRng, RngCore};
@@ -35,7 +34,7 @@ fn build_inner_envelope_internal<CS: CipherSuite>(
nonce: &[u8],
) -> Result<PublicKey<CS::KeGroup>, ProtocolError> {
let h = Hkdf::<CS::Hash>::new(None, random_pwd);
let mut keypair_seed = vec![0u8; <PrivateKey<CS::KeGroup> as SizedBytes>::Len::to_usize()];
let mut keypair_seed = vec![0u8; <CS::KeGroup as Group>::ScalarLen::USIZE];
h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed)
.map_err(|_| InternalPakeError::HkdfError)?;
let client_static_keypair = KeyPair::<CS::KeGroup>::from_private_key_slice(
@@ -53,7 +52,7 @@ fn recover_keys_internal<CS: CipherSuite>(
nonce: &[u8],
) -> Result<KeyPair<CS::KeGroup>, ProtocolError> {
let h = Hkdf::<CS::Hash>::new(None, random_pwd);
let mut keypair_seed = vec![0u8; <PrivateKey<CS::KeGroup> as SizedBytes>::Len::to_usize()];
let mut keypair_seed = vec![0u8; <CS::KeGroup as Group>::ScalarLen::USIZE];
h.expand(&[nonce, STR_PRIVATE_KEY].concat(), &mut keypair_seed)
.map_err(|_| InternalPakeError::HkdfError)?;
let client_static_keypair = KeyPair::<CS::KeGroup>::from_private_key_slice(
@@ -153,15 +152,15 @@ type SealResult<CS> = (
impl<CS: CipherSuite> Envelope<CS> {
fn hmac_key_size() -> usize {
<CS::Hash as Digest>::OutputSize::to_usize()
<CS::Hash as Digest>::OutputSize::USIZE
}
fn export_key_size() -> usize {
<CS::Hash as Digest>::OutputSize::to_usize()
<CS::Hash as Digest>::OutputSize::USIZE
}
pub(crate) fn len() -> usize {
<CS::Hash as Digest>::OutputSize::to_usize() + NONCE_LEN
<CS::Hash as Digest>::OutputSize::USIZE + NONCE_LEN
}
pub(crate) fn serialize(&self) -> Vec<u8> {
@@ -201,7 +200,7 @@ impl<CS: CipherSuite> Envelope<CS> {
nonce: vec![0u8; NONCE_LEN],
hmac: GenericArray::clone_from_slice(&vec![
0u8;
<CS::Hash as Digest>::OutputSize::to_usize()
<CS::Hash as Digest>::OutputSize::USIZE
]),
}
}
-18
View File
@@ -296,24 +296,6 @@ impl ProtocolError {
}
}
impl<T> From<generic_bytes::TryFromSizedBytesError> for InternalPakeError<T> {
fn from(_: generic_bytes::TryFromSizedBytesError) -> Self {
InternalPakeError::InvalidByteSequence
}
}
impl<T> From<generic_bytes::TryFromSizedBytesError> for PakeError<T> {
fn from(e: generic_bytes::TryFromSizedBytesError) -> Self {
PakeError::CryptoError(e.into())
}
}
impl<T> From<generic_bytes::TryFromSizedBytesError> for ProtocolError<T> {
fn from(e: generic_bytes::TryFromSizedBytesError) -> Self {
PakeError::CryptoError(e.into()).into()
}
}
pub(crate) mod utils {
use super::*;
+2 -2
View File
@@ -31,8 +31,8 @@ pub fn expand_message_xmd<H: Hash>(
dst: &[u8],
len_in_bytes: usize,
) -> Result<Vec<u8>, ProtocolError> {
let b_in_bytes = <H as Digest>::OutputSize::to_usize();
let r_in_bytes = <H as BlockInput>::BlockSize::to_usize();
let b_in_bytes = <H as Digest>::OutputSize::USIZE;
let r_in_bytes = <H as BlockInput>::BlockSize::USIZE;
let ell = div_ceil(len_in_bytes, b_in_bytes);
if ell > 255 {
+50 -35
View File
@@ -18,7 +18,7 @@ use generic_array::{ArrayLength, GenericArray};
use num_bigint::{BigInt, Sign};
use num_integer::Integer;
use num_traits::{One, ToPrimitive};
use once_cell::sync::Lazy;
use once_cell::unsync::Lazy;
use p256_::elliptic_curve::group::prime::PrimeCurveAffine;
use p256_::elliptic_curve::group::GroupEncoding;
use p256_::elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint};
@@ -27,50 +27,41 @@ use p256_::elliptic_curve::Field;
use p256_::{AffinePoint, EncodedPoint, ProjectivePoint};
use rand::{CryptoRng, RngCore};
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2
// `p: 2^256 - 2^224 + 2^192 + 2^96 - 1`
const P: Lazy<BigInt> = Lazy::new(|| {
BigInt::from_str(
"115792089210356248762697446949407573530086143415290314195533631308867097853951",
)
.unwrap()
});
// `A: -3`
const A: Lazy<BigInt> = Lazy::new(|| BigInt::from(-3));
// `B: 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b`
const B: Lazy<BigInt> = Lazy::new(|| {
BigInt::parse_bytes(
b"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
16,
)
.unwrap()
});
// `L: 48`
pub const L: usize = 48;
// `Z: -10`
const Z: Lazy<BigInt> = Lazy::new(|| BigInt::from(-10));
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#[{%22num%22:211,%22gen%22:0},{%22name%22:%22XYZ%22},70,700,0]
// P-256 `n` is defined as `115792089210356248762697446949407573529996955224135760342 422259061068512044369`
pub const N: Lazy<BigInt> = Lazy::new(|| {
BigInt::from_str(
"115792089210356248762697446949407573529996955224135760342422259061068512044369",
)
.unwrap()
});
#[cfg(feature = "p256")]
impl Group for ProjectivePoint {
const SUITE_ID: usize = 0x0003;
// Implements the `hash_to_curve()` function from
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, ProtocolError> {
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-8.2
// `p: 2^256 - 2^224 + 2^192 + 2^96 - 1`
const P: Lazy<BigInt> = Lazy::new(|| {
BigInt::from_str(
"115792089210356248762697446949407573530086143415290314195533631308867097853951",
)
.unwrap()
});
// `A: -3`
const A: Lazy<BigInt> = Lazy::new(|| BigInt::from(-3));
// `B: 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b`
const B: Lazy<BigInt> = Lazy::new(|| {
BigInt::parse_bytes(
b"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
16,
)
.unwrap()
});
// `Z: -10`
const Z: Lazy<BigInt> = Lazy::new(|| BigInt::from(-10));
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3
// `hash_to_curve` calls `hash_to_field` with a `count` of `2`
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
// `hash_to_field` calls `expand_message` with a `len_in_bytes` of `count * L`
let uniform_bytes =
super::expand::expand_message_xmd::<H>(msg, dst, 2 * crate::group::p256::L)?;
let uniform_bytes = super::expand::expand_message_xmd::<H>(msg, dst, 2 * L)?;
// map to curve
let (q0x, q0y) = map_to_curve_simple_swu(&uniform_bytes[..L], &A, &B, &P, &Z);
@@ -93,12 +84,20 @@ impl Group for ProjectivePoint {
// Implements the `HashToScalar()` function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-07.html#section-4.3
fn hash_to_scalar<H: Hash>(input: &[u8], dst: &[u8]) -> Result<Self::Scalar, ProtocolError> {
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#[{%22num%22:211,%22gen%22:0},{%22name%22:%22XYZ%22},70,700,0]
// P-256 `n` is defined as `115792089210356248762697446949407573529996955224135760342 422259061068512044369`
const N: once_cell::unsync::Lazy<BigInt> = once_cell::unsync::Lazy::new(|| {
BigInt::from_str(
"115792089210356248762697446949407573529996955224135760342422259061068512044369",
)
.unwrap()
});
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
// `HashToScalar` is `hash_to_field`
let uniform_bytes =
super::expand::expand_message_xmd::<H>(input, dst, crate::group::p256::L)?;
let uniform_bytes = super::expand::expand_message_xmd::<H>(input, dst, L)?;
let mut bytes = BigInt::from_bytes_be(Sign::Plus, &uniform_bytes)
.mod_floor(&crate::group::p256::N)
.mod_floor(&N)
.to_bytes_be()
.1;
bytes.resize(32, 0);
@@ -410,6 +409,22 @@ mod tests {
#[test]
fn map_to_curve_simple_swu() {
const P: Lazy<BigInt> = Lazy::new(|| {
BigInt::from_str(
"115792089210356248762697446949407573530086143415290314195533631308867097853951",
)
.unwrap()
});
const A: Lazy<BigInt> = Lazy::new(|| BigInt::from(-3));
const B: Lazy<BigInt> = Lazy::new(|| {
BigInt::parse_bytes(
b"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
16,
)
.unwrap()
});
const Z: Lazy<BigInt> = Lazy::new(|| BigInt::from(-10));
// Test vectors taken from https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#appendix-J.1.1
let test_vectors = alloc::vec![
Params {
+21 -27
View File
@@ -15,7 +15,7 @@ use crate::{
key_exchange::traits::{
FromBytes, GenerateKe2Result, GenerateKe3Result, KeyExchange, ToBytes, ToBytesWithPointers,
},
keypair::{KeyPair, PrivateKey, PublicKey, SecretKey, SizedBytesExt},
keypair::{KeyPair, PrivateKey, PublicKey, SecretKey},
serialization::serialize,
};
use alloc::vec;
@@ -26,7 +26,6 @@ use generic_array::{
typenum::{Unsigned, U32},
ArrayLength, GenericArray,
};
use generic_bytes::SizedBytes;
use hkdf::Hkdf;
use hmac::{Hmac, Mac, NewMac};
use rand::{CryptoRng, RngCore};
@@ -214,9 +213,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
}
fn ke2_message_size() -> usize {
NonceLen::to_usize()
+ <G as Group>::ElemLen::to_usize()
+ <<D as FixedOutput>::OutputSize as Unsigned>::to_usize()
NonceLen::USIZE + <G as Group>::ElemLen::USIZE + <D as FixedOutput>::OutputSize::USIZE
}
}
@@ -260,9 +257,9 @@ pub struct Ke1Message<G: Group> {
impl<G: Group> FromBytes for Ke1State<G> {
fn from_bytes<CS: CipherSuite>(bytes: &[u8]) -> Result<Self, PakeError> {
let key_len = <G as Group>::ElemLen::to_usize();
let key_len = <G as Group>::ElemLen::USIZE;
let nonce_len = NonceLen::to_usize();
let nonce_len = NonceLen::USIZE;
let checked_bytes = check_slice_size_atleast(bytes, key_len + nonce_len, "ke1_state")?;
Ok(Self {
@@ -283,11 +280,8 @@ impl<G: Group> ToBytesWithPointers for Ke1State<G> {
#[cfg(test)]
fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![
(
self.client_e_sk.as_ptr(),
<PrivateKey<G> as SizedBytes>::Len::to_usize(),
),
(self.client_nonce.as_ptr(), NonceLen::to_usize()),
(self.client_e_sk.as_ptr(), G::ScalarLen::USIZE),
(self.client_nonce.as_ptr(), NonceLen::USIZE),
]
}
}
@@ -300,10 +294,10 @@ impl<G: Group> ToBytes for Ke1Message<G> {
impl<G: Group> FromBytes for Ke1Message<G> {
fn from_bytes<CS: CipherSuite>(ke1_message_bytes: &[u8]) -> Result<Self, PakeError> {
let nonce_len = NonceLen::to_usize();
let nonce_len = NonceLen::USIZE;
let checked_nonce = check_slice_size(
ke1_message_bytes,
nonce_len + <G as Group>::ElemLen::to_usize(),
nonce_len + <G as Group>::ElemLen::USIZE,
"ke1_message nonce",
)?;
@@ -351,9 +345,9 @@ impl<HashLen: ArrayLength<u8>> ToBytesWithPointers for Ke2State<HashLen> {
#[cfg(test)]
fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![
(self.km3.as_ptr(), HashLen::to_usize()),
(self.hashed_transcript.as_ptr(), HashLen::to_usize()),
(self.session_key.as_ptr(), HashLen::to_usize()),
(self.km3.as_ptr(), HashLen::USIZE),
(self.hashed_transcript.as_ptr(), HashLen::USIZE),
(self.session_key.as_ptr(), HashLen::USIZE),
]
}
}
@@ -370,7 +364,7 @@ pub struct Ke2Message<G: Group, HashLen: ArrayLength<u8>> {
impl<HashLen: ArrayLength<u8>> FromBytes for Ke2State<HashLen> {
fn from_bytes<CS: CipherSuite>(input: &[u8]) -> Result<Self, PakeError> {
let hash_len = HashLen::to_usize();
let hash_len = HashLen::USIZE;
let checked_bytes = check_slice_size(input, 3 * hash_len, "ke2_state")?;
Ok(Self {
@@ -397,8 +391,8 @@ impl<G: Group, HashLen: ArrayLength<u8>> Ke2Message<G, HashLen> {
impl<G: Group, HashLen: ArrayLength<u8>> FromBytes for Ke2Message<G, HashLen> {
fn from_bytes<CS: CipherSuite>(input: &[u8]) -> Result<Self, PakeError> {
let key_len = <G as Group>::ElemLen::to_usize();
let nonce_len = NonceLen::to_usize();
let key_len = <G as Group>::ElemLen::USIZE;
let nonce_len = NonceLen::USIZE;
let checked_nonce = check_slice_size_atleast(input, nonce_len, "ke2_message nonce")?;
let unchecked_server_e_pk = check_slice_size_atleast(
@@ -408,7 +402,7 @@ impl<G: Group, HashLen: ArrayLength<u8>> FromBytes for Ke2Message<G, HashLen> {
)?;
let checked_mac = check_slice_size(
&unchecked_server_e_pk[key_len..],
HashLen::to_usize(),
HashLen::USIZE,
"ke1_message mac",
)?;
@@ -468,7 +462,7 @@ impl<HashLen: ArrayLength<u8>> ToBytes for Ke3Message<HashLen> {
impl<HashLen: ArrayLength<u8>> FromBytes for Ke3Message<HashLen> {
fn from_bytes<CS: CipherSuite>(bytes: &[u8]) -> Result<Self, PakeError> {
let checked_bytes = check_slice_size(bytes, HashLen::to_usize(), "ke3_message")?;
let checked_bytes = check_slice_size(bytes, HashLen::USIZE, "ke3_message")?;
Ok(Self {
mac: GenericArray::clone_from_slice(checked_bytes),
@@ -513,14 +507,14 @@ fn derive_3dh_keys<D: Hash, G: Group, S: SecretKey<G>>(
&handshake_secret,
STR_SERVER_MAC,
b"",
<D as Digest>::OutputSize::to_usize(),
<D as Digest>::OutputSize::USIZE,
)
.map_err(ProtocolError::into_custom)?;
let km3 = hkdf_expand_label::<D>(
&handshake_secret,
STR_CLIENT_MAC,
b"",
<D as Digest>::OutputSize::to_usize(),
<D as Digest>::OutputSize::USIZE,
)
.map_err(ProtocolError::into_custom)?;
@@ -577,13 +571,13 @@ fn derive_secrets<D: Hash>(
hkdf,
label,
hashed_derivation_transcript,
<D as Digest>::OutputSize::to_usize(),
<D as Digest>::OutputSize::USIZE,
)
}
// Generate a random nonce up to NonceLen::to_usize() bytes.
// Generate a random nonce up to NonceLen::USIZE bytes.
fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> GenericArray<u8, NonceLen> {
let mut nonce_bytes = vec![0u8; NonceLen::to_usize()];
let mut nonce_bytes = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut nonce_bytes);
GenericArray::clone_from_slice(&nonce_bytes)
}
+35 -46
View File
@@ -9,32 +9,14 @@
use crate::errors::{InternalPakeError, ProtocolError};
use crate::group::Group;
use alloc::borrow::ToOwned;
use alloc::vec::Vec;
use core::fmt::Debug;
use core::ops::Deref;
#[cfg(test)]
use generic_array::typenum::Unsigned;
use generic_array::{ArrayLength, GenericArray};
use generic_bytes::{SizedBytes, TryFromSizedBytesError};
#[cfg(all(test, feature = "std"))]
use proptest::prelude::*;
#[cfg(all(test, feature = "std"))]
use rand::{rngs::StdRng, SeedableRng};
use rand::{CryptoRng, RngCore};
use zeroize::Zeroize;
/// Convenience extension trait of SizedBytes
pub trait SizedBytesExt: SizedBytes {
/// Convert from bytes
fn from_bytes(bytes: &[u8]) -> Result<Self, TryFromSizedBytesError> {
<Self as SizedBytes>::from_arr(GenericArray::from_slice(bytes))
}
}
// blanket implementation
impl<T> SizedBytesExt for T where T: SizedBytes {}
/// A Keypair trait with public-private verification
#[cfg_attr(
feature = "serialize",
@@ -142,17 +124,20 @@ impl<G: Group> KeyPair<G> {
#[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
alloc::vec![
(self.pk.as_ptr(), G::ElemLen::to_usize()),
(self.sk.as_ptr(), G::ScalarLen::to_usize()),
(self.pk.as_ptr(), G::ElemLen::USIZE),
(self.sk.as_ptr(), G::ScalarLen::USIZE),
]
}
}
#[cfg(all(test, feature = "std"))]
#[cfg(test)]
impl<G: Group + Debug> KeyPair<G> {
/// Test-only strategy returning a proptest Strategy based on
/// generate_random
fn uniform_keypair_strategy() -> BoxedStrategy<Self> {
fn uniform_keypair_strategy() -> proptest::prelude::BoxedStrategy<Self> {
use proptest::prelude::*;
use rand::{rngs::StdRng, SeedableRng};
// The no_shrink is because keypairs should be fixed -- shrinking would cause a different
// keypair to be generated, which appears to not be very useful.
any::<[u8; 32]>()
@@ -223,13 +208,9 @@ impl<L: ArrayLength<u8>> Deref for Key<L> {
// Don't make it implement SizedBytes so that it's not constructible outside of this module.
impl<L: ArrayLength<u8>> Key<L> {
fn to_arr(&self) -> GenericArray<u8, L> {
GenericArray::clone_from_slice(&self.0[..])
}
#[allow(clippy::unnecessary_wraps)]
fn from_arr(key_bytes: &GenericArray<u8, L>) -> Result<Self, TryFromSizedBytesError> {
Ok(Key(key_bytes.to_owned()))
/// Convert to bytes
pub fn to_arr(&self) -> GenericArray<u8, L> {
self.0.clone()
}
}
@@ -268,15 +249,19 @@ impl<G: Group> Deref for PrivateKey<G> {
}
}
impl<G: Group> SizedBytes for PrivateKey<G> {
type Len = G::ScalarLen;
fn to_arr(&self) -> GenericArray<u8, Self::Len> {
self.0.to_arr()
impl<G: Group> PrivateKey<G> {
/// Convert from bytes
pub fn from_arr(key_bytes: GenericArray<u8, G::ScalarLen>) -> Self {
PrivateKey(Key(key_bytes))
}
fn from_arr(key_bytes: &GenericArray<u8, Self::Len>) -> Result<Self, TryFromSizedBytesError> {
Ok(PrivateKey(Key::from_arr(key_bytes)?))
/// Convert from slice
pub fn from_bytes(key_bytes: &[u8]) -> Result<Self, InternalPakeError> {
if key_bytes.len() == G::ScalarLen::USIZE {
Ok(Self::from_arr(GenericArray::from_slice(key_bytes).clone()))
} else {
Err(InternalPakeError::InvalidByteSequence)
}
}
}
@@ -359,15 +344,19 @@ impl<G: Group> Deref for PublicKey<G> {
}
}
impl<G: Group> SizedBytes for PublicKey<G> {
type Len = G::ElemLen;
fn to_arr(&self) -> GenericArray<u8, Self::Len> {
self.0.to_arr()
impl<G: Group> PublicKey<G> {
/// Convert from bytes
pub fn from_arr(key_bytes: GenericArray<u8, G::ElemLen>) -> Self {
Self(Key(key_bytes))
}
fn from_arr(key_bytes: &GenericArray<u8, Self::Len>) -> Result<Self, TryFromSizedBytesError> {
Ok(PublicKey(Key::from_arr(key_bytes)?))
/// Convert from slice
pub fn from_bytes(key_bytes: &[u8]) -> Result<Self, InternalPakeError> {
if key_bytes.len() == G::ElemLen::USIZE {
Ok(Self::from_arr(GenericArray::from_slice(key_bytes).clone()))
} else {
Err(InternalPakeError::InvalidByteSequence)
}
}
}
@@ -378,11 +367,12 @@ mod tests {
use core::slice::from_raw_parts;
use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned;
use proptest::prelude::*;
use rand::rngs::OsRng;
#[test]
fn test_zeroize_key() -> Result<(), ProtocolError> {
let key_len = <RistrettoPoint as Group>::ElemLen::to_usize();
let key_len = <RistrettoPoint as Group>::ElemLen::USIZE;
let mut key = Key::<<RistrettoPoint as Group>::ElemLen>(GenericArray::clone_from_slice(
&alloc::vec![
1u8;
@@ -415,7 +405,6 @@ mod tests {
Ok(())
}
#[cfg(feature = "std")]
proptest! {
#[test]
fn test_ristretto_check(kp in KeyPair::<RistrettoPoint>::uniform_keypair_strategy()) {
@@ -505,7 +494,7 @@ mod tests {
let sk = RistrettoPoint::random_nonzero_scalar(&mut OsRng);
let sk_bytes = RistrettoPoint::scalar_as_bytes(sk);
let sk = RemoteKey(PrivateKey::from_arr(&sk_bytes).unwrap());
let sk = RemoteKey(PrivateKey::from_arr(sk_bytes));
let keypair = KeyPair::from_private_key(sk).unwrap();
let server_setup = ServerSetup::<Default, RemoteKey>::new_with_key(&mut OsRng, keypair);
+2 -4
View File
@@ -748,7 +748,6 @@
//! ```
//! # use curve25519_dalek::ristretto::RistrettoPoint;
//! # use generic_array::{GenericArray, typenum::U32};
//! # use generic_bytes::SizedBytes;
//! # use opaque_ke::{CipherSuite, errors::{InternalPakeError}, keypair::{KeyPair, PrivateKey, PublicKey, SecretKey}, ServerSetup};
//! # use rand::rngs::OsRng;
//! # use zeroize::Zeroize;
@@ -781,8 +780,7 @@
//! fn public_key(
//! &self
//! ) -> Result<PublicKey<RistrettoPoint>, InternalPakeError<Self::Error>> {
//! let pk = YourRemoteKey::public_key(self).map_err(InternalPakeError::Custom)?;
//! PublicKey::from_arr(&pk).map_err(InternalPakeError::from)
//! YourRemoteKey::public_key(self).map(PublicKey::from_arr).map_err(InternalPakeError::Custom)
//! }
//!
//! fn serialize(&self) -> Vec<u8> {
@@ -796,7 +794,7 @@
//! }
//! }
//!
//! # let remote_key = YourRemoteKey(PrivateKey::from_arr(&GenericArray::default()).unwrap());
//! # let remote_key = YourRemoteKey(PrivateKey::from_arr(GenericArray::default()));
//! let keypair = KeyPair::from_private_key(remote_key).unwrap();
//! let server_setup = ServerSetup::<Default, YourRemoteKey>::new_with_key(&mut OsRng, keypair);
//! ```
+10 -11
View File
@@ -14,13 +14,12 @@ use crate::{
},
group::Group,
key_exchange::traits::{FromBytes, KeyExchange, ToBytes},
keypair::{KeyPair, PublicKey, SecretKey, SizedBytesExt},
keypair::{KeyPair, PublicKey, SecretKey},
opaque::ServerSetup,
};
use alloc::vec::Vec;
use digest::Digest;
use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes;
use rand::{CryptoRng, RngCore};
// Messages
@@ -57,7 +56,7 @@ impl<CS: CipherSuite> RegistrationRequest<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
let elem_len = <CS::OprfGroup as Group>::ElemLen::USIZE;
let checked_slice = check_slice_size(input, elem_len, "first_message_bytes")?;
// Check that the message is actually containing an element of the
// correct subgroup
@@ -107,8 +106,8 @@ impl<CS: CipherSuite> RegistrationResponse<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
let elem_len = <CS::OprfGroup as Group>::ElemLen::USIZE;
let key_len = <CS::KeGroup as Group>::ElemLen::USIZE;
let checked_slice =
check_slice_size(input, elem_len + key_len, "registration_response_bytes")?;
@@ -177,8 +176,8 @@ impl<CS: CipherSuite> RegistrationUpload<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
let hash_len = <CS::Hash as Digest>::OutputSize::to_usize();
let key_len = <CS::KeGroup as Group>::ElemLen::USIZE;
let hash_len = <CS::Hash as Digest>::OutputSize::USIZE;
let checked_slice =
check_slice_size_atleast(input, key_len + hash_len, "registration_upload_bytes")?;
let envelope = Envelope::<CS>::deserialize(&checked_slice[key_len + hash_len..])?;
@@ -198,7 +197,7 @@ impl<CS: CipherSuite> RegistrationUpload<CS> {
rng: &mut R,
server_setup: &ServerSetup<CS, S>,
) -> Self {
let mut masking_key = alloc::vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
let mut masking_key = alloc::vec![0u8; <CS::Hash as Digest>::OutputSize::USIZE];
rng.fill_bytes(&mut masking_key);
Self {
@@ -245,7 +244,7 @@ impl<CS: CipherSuite> CredentialRequest<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
let elem_len = <CS::OprfGroup as Group>::ElemLen::USIZE;
let checked_slice = check_slice_size_atleast(input, elem_len, "login_first_message_bytes")?;
@@ -327,8 +326,8 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
let elem_len = <CS::OprfGroup as Group>::ElemLen::USIZE;
let key_len = <CS::KeGroup as Group>::ElemLen::USIZE;
let nonce_len: usize = 32;
let envelope_len = Envelope::<CS>::len();
let masked_response_len = key_len + envelope_len;
+13 -17
View File
@@ -24,7 +24,6 @@ use alloc::vec::Vec;
use core::marker::PhantomData;
use digest::Digest;
use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes;
use hkdf::Hkdf;
use rand::{CryptoRng, RngCore};
use zeroize::Zeroize;
@@ -69,7 +68,7 @@ impl<CS: CipherSuite, S: SecretKey<CS::KeGroup>> ServerSetup<CS, S> {
rng: &mut R,
keypair: KeyPair<CS::KeGroup, S>,
) -> Self {
let mut seed = vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
let mut seed = vec![0u8; <CS::Hash as Digest>::OutputSize::USIZE];
rng.fill_bytes(&mut seed);
Self {
@@ -91,8 +90,8 @@ impl<CS: CipherSuite, S: SecretKey<CS::KeGroup>> ServerSetup<CS, S> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError<S::Error>> {
let seed_len = <CS::Hash as Digest>::OutputSize::to_usize();
let key_len = <PrivateKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
let seed_len = <CS::Hash as Digest>::OutputSize::USIZE;
let key_len = <CS::KeGroup as Group>::ScalarLen::USIZE;
let checked_slice = check_slice_size(input, seed_len + key_len + key_len, "server_setup")?;
Ok(Self {
@@ -149,8 +148,8 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let elem_len = <CS::OprfGroup as Group>::ElemLen::to_usize();
let scalar_len = <CS::OprfGroup as Group>::ScalarLen::to_usize();
let elem_len = <CS::OprfGroup as Group>::ElemLen::USIZE;
let scalar_len = <CS::OprfGroup as Group>::ScalarLen::USIZE;
let min_expected_len = elem_len + scalar_len;
let checked_slice = (if input.len() <= min_expected_len {
Err(InternalPakeError::SizeError {
@@ -332,7 +331,7 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
#[cfg_attr(not(test), allow(unused_variables))]
let (randomized_pwd, h) = Hkdf::<CS::Hash>::extract(None, &password_derived_key);
let mut masking_key = vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
let mut masking_key = vec![0u8; <CS::Hash as Digest>::OutputSize::USIZE];
h.expand(STR_MASKING_KEY, &mut masking_key)
.map_err(|_| InternalPakeError::HkdfError)?;
@@ -490,7 +489,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
/// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let scalar_len = <CS::OprfGroup as Group>::ScalarLen::to_usize();
let scalar_len = <CS::OprfGroup as Group>::ScalarLen::USIZE;
let checked_slice = (if input.len() <= scalar_len {
Err(InternalPakeError::SizeError {
name: "client_login_bytes",
@@ -664,7 +663,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
)?;
let h = Hkdf::<CS::Hash>::new(None, &password_derived_key);
let mut masking_key = vec![0u8; <CS::Hash as Digest>::OutputSize::to_usize()];
let mut masking_key = vec![0u8; <CS::Hash as Digest>::OutputSize::USIZE];
h.expand(STR_MASKING_KEY, &mut masking_key)
.map_err(|_| InternalPakeError::HkdfError)?;
@@ -1029,7 +1028,7 @@ fn oprf_key_from_seed<G: Group, D: Hash>(
oprf_seed: &GenericArray<u8, D::OutputSize>,
credential_identifier: &[u8],
) -> Result<G::Scalar, ProtocolError> {
let mut ikm = vec![0u8; <PrivateKey<G> as SizedBytes>::Len::to_usize()];
let mut ikm = vec![0u8; G::ScalarLen::USIZE];
Hkdf::<D>::from_prk(oprf_seed)
.map_err(|_| InternalPakeError::HkdfError)?
.expand(&[credential_identifier, STR_OPRF_KEY].concat(), &mut ikm)
@@ -1043,8 +1042,7 @@ fn mask_response<CS: CipherSuite>(
server_s_pk: &PublicKey<CS::KeGroup>,
envelope: &Envelope<CS>,
) -> Result<Vec<u8>, ProtocolError> {
let mut xor_pad =
vec![0u8; <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize() + Envelope::<CS>::len()];
let mut xor_pad = vec![0u8; <CS::KeGroup as Group>::ElemLen::USIZE + Envelope::<CS>::len()];
Hkdf::<CS::Hash>::from_prk(masking_key)
.map_err(|_| InternalPakeError::HkdfError)?
.expand(
@@ -1067,8 +1065,7 @@ fn unmask_response<CS: CipherSuite>(
masking_nonce: &[u8],
masked_response: &[u8],
) -> Result<(PublicKey<CS::KeGroup>, Envelope<CS>), ProtocolError> {
let mut xor_pad =
vec![0u8; <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize() + Envelope::<CS>::len()];
let mut xor_pad = vec![0u8; <CS::KeGroup as Group>::ElemLen::USIZE + Envelope::<CS>::len()];
Hkdf::<CS::Hash>::from_prk(masking_key)
.map_err(|_| InternalPakeError::HkdfError)?
.expand(
@@ -1081,9 +1078,8 @@ fn unmask_response<CS: CipherSuite>(
.zip(masked_response.iter())
.map(|(&x1, &x2)| x1 ^ x2)
.collect();
let key_len = <PublicKey<CS::KeGroup> as SizedBytes>::Len::to_usize();
let unchecked_server_s_pk =
PublicKey::from_arr(&GenericArray::clone_from_slice(&plaintext[..key_len]))?;
let key_len = <CS::KeGroup as Group>::ElemLen::USIZE;
let unchecked_server_s_pk = PublicKey::from_bytes(&plaintext[..key_len])?;
let envelope = Envelope::deserialize(&plaintext[key_len..])?;
// Ensure that public key is valid
+11 -15
View File
@@ -12,7 +12,7 @@ use crate::{
traits::{FromBytes, KeyExchange, ToBytes},
tripledh::{NonceLen, TripleDH},
},
keypair::{KeyPair, PublicKey},
keypair::KeyPair,
serialization::{i2osp, os2ip, serialize},
*,
};
@@ -23,7 +23,6 @@ use alloc::vec::Vec;
use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity};
use generic_array::typenum::Unsigned;
use generic_bytes::SizedBytes;
use proptest::{collection::vec, prelude::*};
use rand::{rngs::OsRng, RngCore};
@@ -79,8 +78,8 @@ fn server_registration_roundtrip() {
// Construct a mock envelope
let mut mock_envelope_bytes = Vec::new();
mock_envelope_bytes.extend_from_slice(&vec![0; NonceLen::to_usize()]); // empty nonce
// mock_envelope_bytes.extend_from_slice(&ciphertext); // ciphertext which is an encrypted private key
mock_envelope_bytes.extend_from_slice(&vec![0; NonceLen::USIZE]); // empty nonce
// mock_envelope_bytes.extend_from_slice(&ciphertext); // ciphertext which is an encrypted private key
mock_envelope_bytes.extend_from_slice(&[0; MAC_SIZE]); // length-MAC_SIZE hmac
let mock_client_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
@@ -157,7 +156,7 @@ fn registration_upload_roundtrip() {
let mut nonce = [0u8; 32];
rng.fill_bytes(&mut nonce);
let mut masking_key = vec![0u8; <sha2::Sha512 as Digest>::OutputSize::to_usize()];
let mut masking_key = vec![0u8; <sha2::Sha512 as Digest>::OutputSize::USIZE];
rng.fill_bytes(&mut masking_key);
let (envelope, _, _) =
@@ -182,7 +181,7 @@ fn credential_request_roundtrip() {
let alpha_bytes = alpha.to_arr().to_vec();
let client_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
let mut client_nonce = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut client_nonce);
let ke1m: Vec<u8> = [&client_nonce[..], &client_e_kp.public()].concat();
@@ -217,17 +216,14 @@ fn credential_response_roundtrip() {
let mut masking_nonce = vec![0u8; 32];
rng.fill_bytes(&mut masking_nonce);
let mut masked_response = vec![
0u8;
<PublicKey<RistrettoPoint> as SizedBytes>::Len::to_usize()
+ Envelope::<Default>::len()
];
let mut masked_response =
vec![0u8; <RistrettoPoint as Group>::ElemLen::USIZE + Envelope::<Default>::len()];
rng.fill_bytes(&mut masked_response);
let server_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
let mut mac = [0u8; MAC_SIZE];
rng.fill_bytes(&mut mac);
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
let mut server_nonce = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut server_nonce);
let ke2m: Vec<u8> = [&server_nonce[..], &server_e_kp.public(), &mac[..]].concat();
@@ -280,7 +276,7 @@ fn client_login_roundtrip() {
let sc = <RistrettoPoint as Group>::random_nonzero_scalar(&mut rng);
let client_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
let mut client_nonce = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut client_nonce);
let serialized_credential_request = b"serialized credential_request".to_vec();
@@ -304,7 +300,7 @@ fn ke1_message_roundtrip() {
let mut rng = OsRng;
let client_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
let mut client_nonce = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut client_nonce);
let ke1m: Vec<u8> = [&client_nonce[..], &client_e_kp.public()].concat();
@@ -323,7 +319,7 @@ fn ke2_message_roundtrip() {
let server_e_kp = KeyPair::<<Default as CipherSuite>::OprfGroup>::generate_random(&mut rng);
let mut mac = [0u8; MAC_SIZE];
rng.fill_bytes(&mut mac);
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
let mut server_nonce = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut server_nonce);
let ke2m: Vec<u8> = [&server_nonce[..], &server_e_kp.public(), &mac[..]].concat();
+1 -1
View File
@@ -37,7 +37,7 @@ impl<D: Hash> SlowHash<D> for argon2::Argon2<'_> {
input: GenericArray<u8, <D as Digest>::OutputSize>,
) -> Result<Vec<u8>, InternalPakeError> {
let params = argon2::Argon2::default();
let mut output = alloc::vec![0u8; <D as Digest>::OutputSize::to_usize()];
let mut output = alloc::vec![0u8; <D as Digest>::OutputSize::USIZE];
params
.hash_password_into(
argon2::Algorithm::Argon2id,
+2 -6
View File
@@ -14,7 +14,6 @@ use alloc::vec;
use alloc::vec::Vec;
use core::slice::from_raw_parts;
use curve25519_dalek::{ristretto::RistrettoPoint, traits::Identity};
use generic_bytes::SizedBytes;
use rand::rngs::OsRng;
use serde_json::Value;
use zeroize::Zeroize;
@@ -149,7 +148,6 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameters {
}
}
#[cfg(feature = "std")]
fn stringify_test_vectors(p: &TestVectorParameters) -> alloc::string::String {
let mut s = alloc::string::String::new();
s.push_str("{\n");
@@ -273,7 +271,6 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> alloc::string::String {
s
}
#[cfg(feature = "std")]
fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
use crate::{group::Group, key_exchange::tripledh::NonceLen, keypair::KeyPair};
use generic_array::typenum::Unsigned;
@@ -298,9 +295,9 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
rng.fill_bytes(&mut masking_nonce);
let mut envelope_nonce = [0u8; 32];
rng.fill_bytes(&mut envelope_nonce);
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
let mut client_nonce = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut client_nonce);
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
let mut server_nonce = vec![0u8; NonceLen::USIZE];
rng.fill_bytes(&mut server_nonce);
let fake_sk: Vec<u8> = fake_kp.private().to_vec();
@@ -448,7 +445,6 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
}
}
#[cfg(feature = "std")]
#[test]
fn generate_test_vectors() {
let parameters = generate_parameters::<RistrettoSha5123dhNoSlowHash>();
+3 -4
View File
@@ -4,15 +4,14 @@
// LICENSE file in the root directory of this source tree.
use crate::{
ciphersuite::CipherSuite, errors::*, key_exchange::tripledh::TripleDH, keypair::PrivateKey,
opaque::*, slow_hash::NoOpHash, tests::mock_rng::CycleRng, *,
ciphersuite::CipherSuite, errors::*, group::Group, key_exchange::tripledh::TripleDH, opaque::*,
slow_hash::NoOpHash, tests::mock_rng::CycleRng, *,
};
use alloc::string::ToString;
use alloc::vec::Vec;
use alloc::{format, vec};
use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned;
use generic_bytes::SizedBytes;
use serde_json::Value;
// Tests
@@ -755,7 +754,7 @@ fn populate_test_vectors<CS: CipherSuite>(values: &Value) -> TestVectorParameter
dummy_private_key: parse_default!(
values,
"client_private_key",
vec![0u8; <PrivateKey<CS::OprfGroup> as SizedBytes>::Len::to_usize()]
vec![0u8; <CS::OprfGroup as Group>::ScalarLen::USIZE]
),
dummy_masking_key: parse_default!(values, "masking_key", vec![0u8; 64]),
context: parse!(values, "Context"),