Start integrating the derivable SizedBytes
- just derive it on Key and KeyPair for now
This commit is contained in:
Generated
+22
@@ -335,6 +335,26 @@ dependencies = [
|
||||
"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]]
|
||||
name = "getrandom"
|
||||
version = "0.1.14"
|
||||
@@ -518,6 +538,8 @@ dependencies = [
|
||||
"displaydoc",
|
||||
"fiat-crypto",
|
||||
"generic-array",
|
||||
"generic-bytes",
|
||||
"generic-bytes-derive",
|
||||
"hex",
|
||||
"hkdf",
|
||||
"hmac 0.9.0",
|
||||
|
||||
@@ -22,6 +22,8 @@ digest = "0.9.0"
|
||||
displaydoc = "0.1.7"
|
||||
fiat-crypto = { version = "0.1.5"}
|
||||
generic-array = "0.14.4"
|
||||
generic-bytes = { version = "0.1.0" }
|
||||
generic-bytes-derive = { version = "0.1.0" }
|
||||
hkdf = "0.9.0"
|
||||
hmac = "0.9.0"
|
||||
rand_core = "0.5.1"
|
||||
|
||||
@@ -10,6 +10,8 @@ use thiserror::Error;
|
||||
/// Represents an error in the manipulation of internal cryptographic data
|
||||
#[derive(Debug, Display, Error)]
|
||||
pub enum InternalPakeError {
|
||||
/// Deserializing from a byte sequence failed
|
||||
InvalidByteSequence,
|
||||
/// Invalid length for {name}: expected {len}, but is actually {actual_len}.
|
||||
SizeError {
|
||||
/// 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 {
|
||||
use super::*;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ use generic_array::{
|
||||
typenum::{U32, U64},
|
||||
ArrayLength, GenericArray,
|
||||
};
|
||||
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use std::ops::Mul;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
errors::{utils::check_slice_size, InternalPakeError, PakeError, ProtocolError},
|
||||
hash::Hash,
|
||||
key_exchange::traits::{KeyExchange, ToBytes},
|
||||
keypair::{KeyPair, SizedBytes},
|
||||
keypair::{KeyPair, SizedBytesExt},
|
||||
serialization::serialize,
|
||||
};
|
||||
use digest::{Digest, FixedOutput};
|
||||
@@ -16,6 +16,7 @@ use generic_array::{
|
||||
typenum::{Unsigned, U32},
|
||||
ArrayLength, GenericArray,
|
||||
};
|
||||
use generic_bytes::SizedBytes;
|
||||
use hkdf::Hkdf;
|
||||
use hmac::{Hmac, Mac, NewMac};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
+19
-84
@@ -5,12 +5,10 @@
|
||||
|
||||
//! Contains the keypair types that must be supplied for the OPAQUE API
|
||||
|
||||
use crate::errors::{utils::check_slice_size, InternalPakeError};
|
||||
use generic_array::{
|
||||
sequence::Concat,
|
||||
typenum::{Sum, Unsigned, U32},
|
||||
ArrayLength, GenericArray,
|
||||
};
|
||||
use crate::errors::InternalPakeError;
|
||||
use generic_array::{typenum::U32, GenericArray};
|
||||
use generic_bytes::{SizedBytes, TryFromSizedBytesError};
|
||||
use generic_bytes_derive::{SizedBytes, TryFromForSizedBytes};
|
||||
#[cfg(test)]
|
||||
use proptest::prelude::*;
|
||||
#[cfg(test)]
|
||||
@@ -20,25 +18,18 @@ use std::convert::TryInto;
|
||||
use std::fmt::Debug;
|
||||
use x25519_dalek::{PublicKey, StaticSecret};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::ops::Deref;
|
||||
|
||||
use std::ops::{Add, Deref};
|
||||
|
||||
/// A trait for sized key material that can be represented within a fixed byte
|
||||
/// array size, used to represent our DH key types
|
||||
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>;
|
||||
// Pub(crate) convenience extension trait of SizedBytes for our purposes
|
||||
pub(crate) trait SizedBytesExt: SizedBytes {
|
||||
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
|
||||
pub trait KeyPair: Sized {
|
||||
/// The single key representation must have a specific byte size itself
|
||||
@@ -92,62 +83,9 @@ trait KeyPairExt: KeyPair + Debug {
|
||||
#[cfg(test)]
|
||||
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]
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, TryFromForSizedBytes)]
|
||||
#[ErrorType = "::generic_bytes::TryFromSizedBytesError"]
|
||||
#[repr(transparent)]
|
||||
pub struct Key(Vec<u8>);
|
||||
|
||||
@@ -166,17 +104,14 @@ impl SizedBytes for Key {
|
||||
GenericArray::clone_from_slice(&self.0[..])
|
||||
}
|
||||
|
||||
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")?;
|
||||
Ok(Key(checked_bytes.to_vec()))
|
||||
fn from_arr(key_bytes: &GenericArray<u8, Self::Len>) -> Result<Self, TryFromSizedBytesError> {
|
||||
Ok(Key(key_bytes.to_vec()))
|
||||
}
|
||||
}
|
||||
|
||||
try_from_and_to_bytes_using_sized_bytes!(Key);
|
||||
|
||||
/// 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 {
|
||||
pk: Key,
|
||||
sk: Key,
|
||||
|
||||
+9
-9
@@ -40,7 +40,7 @@
|
||||
//! ## Setup
|
||||
//! 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::ciphersuite::CipherSuite;
|
||||
//! # struct Default;
|
||||
@@ -72,7 +72,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::ServerRegistration,
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -102,7 +102,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::ClientRegistration,
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -135,7 +135,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::{ClientRegistration, ServerRegistration},
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -169,7 +169,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::{ClientRegistration, ServerRegistration},
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -211,7 +211,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::{ClientRegistration, ServerRegistration, ServerLogin, LoginThirdMessage},
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -241,7 +241,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, LoginThirdMessage},
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -285,7 +285,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage},
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -340,7 +340,7 @@
|
||||
//! # use opaque_ke::{
|
||||
//! # errors::ProtocolError,
|
||||
//! # opaque::{ClientRegistration, ServerRegistration, ClientLogin, ServerLogin, LoginThirdMessage},
|
||||
//! # keypair::{KeyPair, X25519KeyPair, SizedBytes},
|
||||
//! # keypair::{KeyPair, X25519KeyPair},
|
||||
//! # slow_hash::NoOpHash,
|
||||
//! # };
|
||||
//! # use opaque_ke::ciphersuite::CipherSuite;
|
||||
|
||||
+5
-4
@@ -15,7 +15,7 @@ use crate::{
|
||||
group::Group,
|
||||
hash::Hash,
|
||||
key_exchange::traits::{KeyExchange, ToBytes},
|
||||
keypair::{KeyPair, SizedBytes},
|
||||
keypair::{KeyPair, SizedBytesExt},
|
||||
oprf,
|
||||
serialization::{
|
||||
serialize, tokenize, u8_to_credential_type, CredentialType, ProtocolMessageType,
|
||||
@@ -23,6 +23,7 @@ use crate::{
|
||||
slow_hash::SlowHash,
|
||||
};
|
||||
use generic_array::{typenum::Unsigned, GenericArray};
|
||||
use generic_bytes::SizedBytes;
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
use std::collections::HashMap;
|
||||
use std::{convert::TryFrom, marker::PhantomData};
|
||||
@@ -640,7 +641,7 @@ impl<CS: CipherSuite> ClientRegistration<CS> {
|
||||
/// # 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::keypair::KeyPair;
|
||||
/// use rand_core::{OsRng, RngCore};
|
||||
@@ -822,7 +823,7 @@ where
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use opaque_ke::{opaque::*, keypair::{X25519KeyPair, SizedBytes}};
|
||||
/// use opaque_ke::{opaque::*, keypair::X25519KeyPair};
|
||||
/// # use opaque_ke::errors::ProtocolError;
|
||||
/// use rand_core::{OsRng, RngCore};
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
@@ -898,7 +899,7 @@ where
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use opaque_ke::{opaque::*, keypair::{KeyPair, X25519KeyPair, SizedBytes}};
|
||||
/// use opaque_ke::{opaque::*, keypair::{KeyPair, X25519KeyPair}};
|
||||
/// # use opaque_ke::errors::ProtocolError;
|
||||
/// use rand_core::{OsRng, RngCore};
|
||||
/// use opaque_ke::ciphersuite::CipherSuite;
|
||||
|
||||
@@ -11,12 +11,13 @@ use crate::{
|
||||
traits::{KeyExchange, ToBytes},
|
||||
tripledh::{TripleDH, NONCE_LEN},
|
||||
},
|
||||
keypair::{KeyPair, SizedBytes, X25519KeyPair},
|
||||
keypair::{KeyPair, X25519KeyPair},
|
||||
opaque::*,
|
||||
serialization::{serialize, ProtocolMessageType},
|
||||
};
|
||||
|
||||
use curve25519_dalek::ristretto::RistrettoPoint;
|
||||
use generic_bytes::SizedBytes;
|
||||
use proptest::{collection::vec, prelude::*};
|
||||
use rand_core::{OsRng, RngCore};
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ use crate::{
|
||||
errors::*,
|
||||
group::Group,
|
||||
key_exchange::tripledh::{TripleDH, NONCE_LEN},
|
||||
keypair::{Key, KeyPair, SizedBytes, X25519KeyPair},
|
||||
keypair::{Key, KeyPair, X25519KeyPair},
|
||||
opaque::*,
|
||||
slow_hash::NoOpHash,
|
||||
tests::mock_rng::CycleRng,
|
||||
};
|
||||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
use generic_array::GenericArray;
|
||||
use generic_bytes::SizedBytes;
|
||||
use rand_core::{OsRng, RngCore};
|
||||
use serde_json::Value;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
Reference in New Issue
Block a user