Merge pull request #77 from huitseeker/sizedbytes

Start integrating the derivable SizedBytes
This commit is contained in:
François Garillot
2020-11-04 20:34:51 -05:00
committed by GitHub
10 changed files with 84 additions and 100 deletions
Generated
+22
View File
@@ -335,6 +335,26 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "generic-bytes"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6638d839bbd1cea640d8c5348dd82e0d545dbd364f3c2a251646eaf2ef0773b"
dependencies = [
"generic-array",
]
[[package]]
name = "generic-bytes-derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4257fe99e64e321c197164da8ae22f7a3c074a5b2519072866e2d38bc1ca59e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.1.14" version = "0.1.14"
@@ -518,6 +538,8 @@ dependencies = [
"displaydoc", "displaydoc",
"fiat-crypto", "fiat-crypto",
"generic-array", "generic-array",
"generic-bytes",
"generic-bytes-derive",
"hex", "hex",
"hkdf", "hkdf",
"hmac 0.9.0", "hmac 0.9.0",
+2
View File
@@ -22,6 +22,8 @@ digest = "0.9.0"
displaydoc = "0.1.7" displaydoc = "0.1.7"
fiat-crypto = { version = "0.1.5"} fiat-crypto = { version = "0.1.5"}
generic-array = "0.14.4" generic-array = "0.14.4"
generic-bytes = { version = "0.1.0" }
generic-bytes-derive = { version = "0.1.0" }
hkdf = "0.9.0" hkdf = "0.9.0"
hmac = "0.9.0" hmac = "0.9.0"
rand_core = "0.5.1" rand_core = "0.5.1"
+20
View File
@@ -10,6 +10,8 @@ use thiserror::Error;
/// Represents an error in the manipulation of internal cryptographic data /// Represents an error in the manipulation of internal cryptographic data
#[derive(Debug, Display, Error)] #[derive(Debug, Display, Error)]
pub enum InternalPakeError { pub enum InternalPakeError {
/// Deserializing from a byte sequence failed
InvalidByteSequence,
/// Invalid length for {name}: expected {len}, but is actually {actual_len}. /// Invalid length for {name}: expected {len}, but is actually {actual_len}.
SizeError { SizeError {
/// name /// name
@@ -116,6 +118,24 @@ impl From<::std::convert::Infallible> for ProtocolError {
} }
} }
impl From<generic_bytes::TryFromSizedBytesError> for InternalPakeError {
fn from(_: generic_bytes::TryFromSizedBytesError) -> Self {
InternalPakeError::InvalidByteSequence
}
}
impl From<generic_bytes::TryFromSizedBytesError> for PakeError {
fn from(e: generic_bytes::TryFromSizedBytesError) -> Self {
PakeError::CryptoError(e.into())
}
}
impl From<generic_bytes::TryFromSizedBytesError> for ProtocolError {
fn from(e: generic_bytes::TryFromSizedBytesError) -> Self {
PakeError::CryptoError(e.into()).into()
}
}
pub(crate) mod utils { pub(crate) mod utils {
use super::*; use super::*;
+1
View File
@@ -17,6 +17,7 @@ use generic_array::{
typenum::{U32, U64}, typenum::{U32, U64},
ArrayLength, GenericArray, ArrayLength, GenericArray,
}; };
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use std::ops::Mul; use std::ops::Mul;
use zeroize::Zeroize; use zeroize::Zeroize;
+2 -1
View File
@@ -8,7 +8,7 @@ use crate::{
errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError}, errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError},
hash::Hash, hash::Hash,
key_exchange::traits::{KeyExchange, ToBytes}, key_exchange::traits::{KeyExchange, ToBytes},
keypair::{KeyPair, SizedBytes}, keypair::{KeyPair, SizedBytesExt},
serialization::serialize, serialization::serialize,
}; };
use digest::{Digest, FixedOutput}; use digest::{Digest, FixedOutput};
@@ -16,6 +16,7 @@ use generic_array::{
typenum::{Unsigned, U32}, typenum::{Unsigned, U32},
ArrayLength, GenericArray, ArrayLength, GenericArray,
}; };
use generic_bytes::SizedBytes;
use hkdf::Hkdf; use hkdf::Hkdf;
use hmac::{Hmac, Mac, NewMac}; use hmac::{Hmac, Mac, NewMac};
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
+19 -84
View File
@@ -5,12 +5,10 @@
//! Contains the keypair types that must be supplied for the OPAQUE API //! Contains the keypair types that must be supplied for the OPAQUE API
use crate::errors::{utils::check_slice_size, InternalPakeError}; use crate::errors::InternalPakeError;
use generic_array::{ use generic_array::{typenum::U32, GenericArray};
sequence::Concat, use generic_bytes::{SizedBytes, TryFromSizedBytesError};
typenum::{Sum, Unsigned, U32}, use generic_bytes_derive::{SizedBytes, TryFromForSizedBytes};
ArrayLength, GenericArray,
};
#[cfg(test)] #[cfg(test)]
use proptest::prelude::*; use proptest::prelude::*;
#[cfg(test)] #[cfg(test)]
@@ -20,25 +18,18 @@ use std::convert::TryInto;
use std::fmt::Debug; use std::fmt::Debug;
use x25519_dalek::{PublicKey, StaticSecret}; use x25519_dalek::{PublicKey, StaticSecret};
use std::convert::TryFrom; use std::ops::Deref;
use std::ops::{Add, Deref}; // Pub(crate) convenience extension trait of SizedBytes for our purposes
pub(crate) trait SizedBytesExt: SizedBytes {
/// A trait for sized key material that can be represented within a fixed byte fn from_bytes(bytes: &[u8]) -> Result<Self, TryFromSizedBytesError> {
/// array size, used to represent our DH key types <Self as SizedBytes>::from_arr(GenericArray::from_slice(bytes))
pub trait SizedBytes: Sized + PartialEq { }
/// The typed representation of the byte length
type Len: ArrayLength<u8>;
/// Converts this sized key material to a `GenericArray` of the same
/// size. One can convert this to a `&[u8]` with `GenericArray::as_slice()`
/// but the size information is then lost from the type.
fn to_arr(&self) -> GenericArray<u8, Self::Len>;
/// How to parse such sized material from a byte slice.
fn from_bytes(key_bytes: &[u8]) -> Result<Self, InternalPakeError>;
} }
// blanket implementation
impl<T> SizedBytesExt for T where T: SizedBytes {}
/// A Keypair trait with public-private verification /// A Keypair trait with public-private verification
pub trait KeyPair: Sized { pub trait KeyPair: Sized {
/// The single key representation must have a specific byte size itself /// The single key representation must have a specific byte size itself
@@ -92,62 +83,9 @@ trait KeyPairExt: KeyPair + Debug {
#[cfg(test)] #[cfg(test)]
impl<KP> KeyPairExt for KP where KP: KeyPair + Debug {} impl<KP> KeyPairExt for KP where KP: KeyPair + Debug {}
/// This assumes you have defined a SizedBytes instance for a `T`, and defines:
/// - an `impl TryFrom<&[u8b], Error = InternalPakeError>` for a non-generic `T`
/// - an `fn to_bytes(&self) -> Vec<u8>` in an `impl T` block
///
/// Because SizedBytes has a strong notion of size, and TryFrom/to_bytes does
/// not, it's better to use this macro than the one above, where possible.
macro_rules! try_from_and_to_bytes_using_sized_bytes {
($sized_type: ident) => {
impl TryFrom<&[u8]> for $sized_type {
type Error = InternalPakeError;
fn try_from(bytes: &[u8]) -> Result<Self, InternalPakeError> {
<$sized_type as SizedBytes>::from_bytes(bytes)
}
}
#[allow(dead_code)]
impl $sized_type {
fn to_bytes(&self) -> Vec<u8> {
self.to_arr().to_vec()
}
}
};
}
/// This is a blanket implementation of SizedBytes for any instance of KeyPair
/// with any length of keys. This encodes that we serialize the public key
/// first, followed by the private key in binary formats (and expect it in this
/// order upon decoding).
impl<T, KP> SizedBytes for KP
where
T: SizedBytes + Clone,
KP: KeyPair<Repr = T> + PartialEq,
T::Len: Add<T::Len>,
Sum<T::Len, T::Len>: ArrayLength<u8>,
{
type Len = Sum<T::Len, T::Len>;
fn to_arr(&self) -> GenericArray<u8, Self::Len> {
let private = self.private().to_arr();
let public = self.public().to_arr();
public.concat(private)
}
fn from_bytes(key_bytes: &[u8]) -> Result<Self, InternalPakeError> {
let checked_bytes =
check_slice_size(key_bytes, <Self::Len as Unsigned>::to_usize(), "key_bytes")?;
let single_key_len = <<KP::Repr as SizedBytes>::Len as Unsigned>::to_usize();
let public = <T as SizedBytes>::from_bytes(&checked_bytes[..single_key_len])?;
let private = <T as SizedBytes>::from_bytes(&checked_bytes[single_key_len..])?;
KP::new(public, private)
}
}
/// A minimalist key type built around [u8;32] /// A minimalist key type built around [u8;32]
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone, TryFromForSizedBytes)]
#[ErrorType = "::generic_bytes::TryFromSizedBytesError"]
#[repr(transparent)] #[repr(transparent)]
pub struct Key(Vec<u8>); pub struct Key(Vec<u8>);
@@ -166,17 +104,14 @@ impl SizedBytes for Key {
GenericArray::clone_from_slice(&self.0[..]) GenericArray::clone_from_slice(&self.0[..])
} }
fn from_bytes(key_bytes: &[u8]) -> Result<Self, InternalPakeError> { fn from_arr(key_bytes: &GenericArray<u8, Self::Len>) -> Result<Self, TryFromSizedBytesError> {
let checked_bytes = Ok(Key(key_bytes.to_vec()))
check_slice_size(key_bytes, <Self::Len as Unsigned>::to_usize(), "key_bytes")?;
Ok(Key(checked_bytes.to_vec()))
} }
} }
try_from_and_to_bytes_using_sized_bytes!(Key);
/// A representation of an X25519 keypair according to RFC7748 /// A representation of an X25519 keypair according to RFC7748
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, SizedBytes, TryFromForSizedBytes)]
#[ErrorType = "::generic_bytes::TryFromSizedBytesError"]
pub struct X25519KeyPair { pub struct X25519KeyPair {
pk: Key, pk: Key,
sk: Key, sk: Key,
+9 -9
View File
@@ -40,7 +40,7 @@
//! ## Setup //! ## Setup
//! To setup the protocol, the server begins by generating a static keypair: //! To setup the protocol, the server begins by generating a static keypair:
//! ``` //! ```
//! # use opaque_ke::keypair::{KeyPair, X25519KeyPair, SizedBytes}; //! # use opaque_ke::keypair::{KeyPair, X25519KeyPair};
//! # use opaque_ke::errors::ProtocolError; //! # use opaque_ke::errors::ProtocolError;
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
//! # struct Default; //! # struct Default;
@@ -72,7 +72,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::ServerRegistration, //! # opaque::ServerRegistration,
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
@@ -102,7 +102,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::ClientRegistration, //! # opaque::ClientRegistration,
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
@@ -135,7 +135,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::{ClientRegistration, ServerRegistration}, //! # opaque::{ClientRegistration, ServerRegistration},
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
@@ -169,7 +169,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::{ClientRegistration, ServerRegistration}, //! # opaque::{ClientRegistration, ServerRegistration},
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
@@ -211,7 +211,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::{ClientRegistration, ServerRegistration, ServerLogin, LoginThirdMessage}, //! # opaque::{ClientRegistration, ServerRegistration, ServerLogin, LoginThirdMessage},
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
@@ -241,7 +241,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, LoginThirdMessage}, //! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, LoginThirdMessage},
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
@@ -285,7 +285,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage}, //! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage},
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
@@ -340,7 +340,7 @@
//! # use opaque_ke::{ //! # use opaque_ke::{
//! # errors::ProtocolError, //! # errors::ProtocolError,
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage}, //! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage},
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes}, //! # keypair::{KeyPair, X25519KeyPair},
//! # slow_hash::NoOpHash, //! # slow_hash::NoOpHash,
//! # }; //! # };
//! # use opaque_ke::ciphersuite::CipherSuite; //! # use opaque_ke::ciphersuite::CipherSuite;
+5 -4
View File
@@ -15,7 +15,7 @@ use crate::{
group::Group, group::Group,
hash::Hash, hash::Hash,
key_exchange::traits::{KeyExchange, ToBytes}, key_exchange::traits::{KeyExchange, ToBytes},
keypair::{KeyPair, SizedBytes}, keypair::{KeyPair, SizedBytesExt},
oprf, oprf,
serialization::{ serialization::{
serialize, tokenize, u8_to_credential_type, CredentialType, ProtocolMessageType, serialize, tokenize, u8_to_credential_type, CredentialType, ProtocolMessageType,
@@ -23,6 +23,7 @@ use crate::{
slow_hash::SlowHash, slow_hash::SlowHash,
}; };
use generic_array::{typenum::Unsigned, GenericArray}; use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes;
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};
use std::collections::HashMap; use std::collections::HashMap;
use std::{convert::TryFrom, marker::PhantomData}; use std::{convert::TryFrom, marker::PhantomData};
@@ -628,7 +629,7 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use opaque_ke::{opaque::{ClientRegistration, ServerRegistration}, keypair::{X25519KeyPair, SizedBytes}}; /// use opaque_ke::{opaque::{ClientRegistration, ServerRegistration}, keypair::X25519KeyPair};
/// # use opaque_ke::errors::ProtocolError; /// # use opaque_ke::errors::ProtocolError;
/// # use opaque_ke::keypair::KeyPair; /// # use opaque_ke::keypair::KeyPair;
/// use rand_core::{OsRng, RngCore}; /// use rand_core::{OsRng, RngCore};
@@ -810,7 +811,7 @@ where
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use opaque_ke::{opaque::*, keypair::{X25519KeyPair, SizedBytes}}; /// use opaque_ke::{opaque::*, keypair::X25519KeyPair};
/// # use opaque_ke::errors::ProtocolError; /// # use opaque_ke::errors::ProtocolError;
/// use rand_core::{OsRng, RngCore}; /// use rand_core::{OsRng, RngCore};
/// use opaque_ke::ciphersuite::CipherSuite; /// use opaque_ke::ciphersuite::CipherSuite;
@@ -886,7 +887,7 @@ where
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use opaque_ke::{opaque::*, keypair::{KeyPair, X25519KeyPair, SizedBytes}}; /// use opaque_ke::{opaque::*, keypair::{KeyPair, X25519KeyPair}};
/// # use opaque_ke::errors::ProtocolError; /// # use opaque_ke::errors::ProtocolError;
/// use rand_core::{OsRng, RngCore}; /// use rand_core::{OsRng, RngCore};
/// use opaque_ke::ciphersuite::CipherSuite; /// use opaque_ke::ciphersuite::CipherSuite;
+2 -1
View File
@@ -11,12 +11,13 @@ use crate::{
traits::{KeyExchange, ToBytes}, traits::{KeyExchange, ToBytes},
tripledh::{TripleDH, NONCE_LEN}, tripledh::{TripleDH, NONCE_LEN},
}, },
keypair::{KeyPair, SizedBytes, X25519KeyPair}, keypair::{KeyPair, X25519KeyPair},
opaque::*, opaque::*,
serialization::{serialize, ProtocolMessageType}, serialization::{serialize, ProtocolMessageType},
}; };
use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::ristretto::RistrettoPoint;
use generic_bytes::SizedBytes;
use proptest::{collection::vec, prelude::*}; use proptest::{collection::vec, prelude::*};
use rand_core::{OsRng, RngCore}; use rand_core::{OsRng, RngCore};
+2 -1
View File
@@ -8,13 +8,14 @@ use crate::{
errors::*, errors::*,
group::Group, group::Group,
key_exchange::tripledh::{TripleDH, NONCE_LEN}, key_exchange::tripledh::{TripleDH, NONCE_LEN},
keypair::{Key, KeyPair, SizedBytes, X25519KeyPair}, keypair::{Key, KeyPair, X25519KeyPair},
opaque::*, opaque::*,
slow_hash::NoOpHash, slow_hash::NoOpHash,
tests::mock_rng::CycleRng, tests::mock_rng::CycleRng,
}; };
use curve25519_dalek::edwards::EdwardsPoint; use curve25519_dalek::edwards::EdwardsPoint;
use generic_array::GenericArray; use generic_array::GenericArray;
use generic_bytes::SizedBytes;
use rand_core::{OsRng, RngCore}; use rand_core::{OsRng, RngCore};
use serde_json::Value; use serde_json::Value;
use std::convert::TryFrom; use std::convert::TryFrom;