Enforce public vs private keys via types

This commit is contained in:
Valentin Tolmer
2021-06-15 14:47:35 -07:00
committed by Kevin Lewi
parent cd85efc603
commit 210e0e99df
8 changed files with 139 additions and 77 deletions
+3 -3
View File
@@ -6,7 +6,7 @@
use crate::{ use crate::{
errors::{utils::check_slice_size_atleast, InternalPakeError, PakeError, ProtocolError}, errors::{utils::check_slice_size_atleast, InternalPakeError, PakeError, ProtocolError},
hash::Hash, hash::Hash,
keypair::Key, keypair::PublicKey,
serialization::serialize, serialization::serialize,
}; };
use digest::Digest; use digest::Digest;
@@ -64,7 +64,7 @@ impl InnerEnvelope {
} }
let mode = InnerEnvelopeMode::try_from(input[0])?; let mode = InnerEnvelopeMode::try_from(input[0])?;
let key_len = <Key as SizedBytes>::Len::to_usize(); let key_len = <PublicKey as SizedBytes>::Len::to_usize();
let bytes = &input[1..]; let bytes = &input[1..];
if bytes.len() < NONCE_LEN + key_len { if bytes.len() < NONCE_LEN + key_len {
@@ -248,7 +248,7 @@ impl<D: Hash> Envelope<D> {
let aad = construct_aad(server_s_pk, optional_ids); let aad = construct_aad(server_s_pk, optional_ids);
let opened = self.open_raw(key, &aad)?; let opened = self.open_raw(key, &aad)?;
if opened.plaintext.len() != <Key as SizedBytes>::Len::to_usize() { if opened.plaintext.len() != <PublicKey as SizedBytes>::Len::to_usize() {
// Plaintext should consist of a single key // Plaintext should consist of a single key
return Err(InternalPakeError::UnexpectedEnvelopeContentsError); return Err(InternalPakeError::UnexpectedEnvelopeContentsError);
} }
+5 -5
View File
@@ -8,7 +8,7 @@ use crate::{
errors::{PakeError, ProtocolError}, errors::{PakeError, ProtocolError},
group::Group, group::Group,
hash::Hash, hash::Hash,
keypair::Key, keypair::{PrivateKey, PublicKey},
}; };
use rand::{CryptoRng, RngCore}; use rand::{CryptoRng, RngCore};
use zeroize::Zeroize; use zeroize::Zeroize;
@@ -31,8 +31,8 @@ pub trait KeyExchange<D: Hash, G: Group> {
l1_bytes: Vec<u8>, l1_bytes: Vec<u8>,
l2_bytes: Vec<u8>, l2_bytes: Vec<u8>,
ke1_message: Self::KE1Message, ke1_message: Self::KE1Message,
client_s_pk: Key, client_s_pk: PublicKey,
server_s_sk: Key, server_s_sk: PrivateKey,
id_u: Vec<u8>, id_u: Vec<u8>,
id_s: Vec<u8>, id_s: Vec<u8>,
e_info: Vec<u8>, e_info: Vec<u8>,
@@ -44,8 +44,8 @@ pub trait KeyExchange<D: Hash, G: Group> {
ke2_message: Self::KE2Message, ke2_message: Self::KE2Message,
ke1_state: &Self::KE1State, ke1_state: &Self::KE1State,
serialized_credential_request: &[u8], serialized_credential_request: &[u8],
server_s_pk: Key, server_s_pk: PublicKey,
client_s_sk: Key, client_s_sk: PrivateKey,
id_u: Vec<u8>, id_u: Vec<u8>,
id_s: Vec<u8>, id_s: Vec<u8>,
) -> Result<(Vec<u8>, Vec<u8>, Self::KE3Message), ProtocolError>; ) -> Result<(Vec<u8>, Vec<u8>, Self::KE3Message), ProtocolError>;
+18 -18
View File
@@ -13,7 +13,7 @@ use crate::{
group::Group, group::Group,
hash::Hash, hash::Hash,
key_exchange::traits::{FromBytes, KeyExchange, ToBytes, ToBytesWithPointers}, key_exchange::traits::{FromBytes, KeyExchange, ToBytes, ToBytesWithPointers},
keypair::{Key, KeyPair, SizedBytesExt}, keypair::{KeyPair, PrivateKey, PublicKey, SizedBytesExt},
serialization::{serialize, tokenize}, serialization::{serialize, tokenize},
}; };
use digest::{Digest, FixedOutput}; use digest::{Digest, FixedOutput};
@@ -78,8 +78,8 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
serialized_credential_request: Vec<u8>, serialized_credential_request: Vec<u8>,
l2_bytes: Vec<u8>, l2_bytes: Vec<u8>,
ke1_message: Self::KE1Message, ke1_message: Self::KE1Message,
client_s_pk: Key, client_s_pk: PublicKey,
server_s_sk: Key, server_s_sk: PrivateKey,
id_u: Vec<u8>, id_u: Vec<u8>,
id_s: Vec<u8>, id_s: Vec<u8>,
e_info: Vec<u8>, e_info: Vec<u8>,
@@ -150,8 +150,8 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
ke2_message: Self::KE2Message, ke2_message: Self::KE2Message,
ke1_state: &Self::KE1State, ke1_state: &Self::KE1State,
serialized_credential_request: &[u8], serialized_credential_request: &[u8],
server_s_pk: Key, server_s_pk: PublicKey,
client_s_sk: Key, client_s_sk: PrivateKey,
id_u: Vec<u8>, id_u: Vec<u8>,
id_s: Vec<u8>, id_s: Vec<u8>,
) -> Result<(Vec<u8>, Vec<u8>, Self::KE3Message), ProtocolError> { ) -> Result<(Vec<u8>, Vec<u8>, Self::KE3Message), ProtocolError> {
@@ -240,7 +240,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
#[derive(PartialEq, Eq, Zeroize, Clone)] #[derive(PartialEq, Eq, Zeroize, Clone)]
#[zeroize(drop)] #[zeroize(drop)]
pub struct Ke1State { pub struct Ke1State {
client_e_sk: Key, client_e_sk: PrivateKey,
client_nonce: GenericArray<u8, NonceLen>, client_nonce: GenericArray<u8, NonceLen>,
} }
@@ -249,7 +249,7 @@ pub struct Ke1State {
pub struct Ke1Message { pub struct Ke1Message {
pub(crate) client_nonce: GenericArray<u8, NonceLen>, pub(crate) client_nonce: GenericArray<u8, NonceLen>,
pub(crate) info: Vec<u8>, pub(crate) info: Vec<u8>,
pub(crate) client_e_pk: Key, pub(crate) client_e_pk: PublicKey,
} }
impl FromBytes for Ke1State { impl FromBytes for Ke1State {
@@ -258,7 +258,7 @@ impl FromBytes for Ke1State {
let checked_bytes = check_slice_size_atleast(bytes, KEY_LEN + nonce_len, "ke1_state")?; let checked_bytes = check_slice_size_atleast(bytes, KEY_LEN + nonce_len, "ke1_state")?;
Ok(Self { Ok(Self {
client_e_sk: Key::from_bytes(&checked_bytes[..KEY_LEN])?, client_e_sk: PrivateKey::from_bytes(&checked_bytes[..KEY_LEN])?,
client_nonce: GenericArray::clone_from_slice( client_nonce: GenericArray::clone_from_slice(
&checked_bytes[KEY_LEN..KEY_LEN + nonce_len], &checked_bytes[KEY_LEN..KEY_LEN + nonce_len],
), ),
@@ -277,7 +277,7 @@ impl ToBytesWithPointers for Ke1State {
vec![ vec![
( (
self.client_e_sk.as_ptr(), self.client_e_sk.as_ptr(),
<Key as SizedBytes>::Len::to_usize(), <PrivateKey as SizedBytes>::Len::to_usize(),
), ),
(self.client_nonce.as_ptr(), NonceLen::to_usize()), (self.client_nonce.as_ptr(), NonceLen::to_usize()),
] ]
@@ -307,7 +307,7 @@ impl FromBytes for Ke1Message {
let unchecked_client_e_pk = let unchecked_client_e_pk =
check_slice_size(&remainder, KEY_LEN, "ke1_message client_e_pk")?; check_slice_size(&remainder, KEY_LEN, "ke1_message client_e_pk")?;
let client_e_pk = let client_e_pk =
KeyPair::<CS::Group>::check_public_key(Key::from_bytes(unchecked_client_e_pk)?)?; KeyPair::<CS::Group>::check_public_key(PublicKey::from_bytes(unchecked_client_e_pk)?)?;
Ok(Self { Ok(Self {
client_nonce: GenericArray::clone_from_slice(&checked_nonce[..nonce_len]), client_nonce: GenericArray::clone_from_slice(&checked_nonce[..nonce_len]),
@@ -363,7 +363,7 @@ impl<HashLen: ArrayLength<u8>> ToBytesWithPointers for Ke2State<HashLen> {
#[derive(Clone)] #[derive(Clone)]
pub struct Ke2Message<HashLen: ArrayLength<u8>> { pub struct Ke2Message<HashLen: ArrayLength<u8>> {
server_nonce: GenericArray<u8, NonceLen>, server_nonce: GenericArray<u8, NonceLen>,
server_e_pk: Key, server_e_pk: PublicKey,
e_info: Vec<u8>, e_info: Vec<u8>,
mac: GenericArray<u8, HashLen>, mac: GenericArray<u8, HashLen>,
} }
@@ -414,7 +414,7 @@ impl<HashLen: ArrayLength<u8>> FromBytes for Ke2Message<HashLen> {
let checked_mac = check_slice_size(&remainder, HashLen::to_usize(), "ke1_message mac")?; let checked_mac = check_slice_size(&remainder, HashLen::to_usize(), "ke1_message mac")?;
// Check the public key bytes // Check the public key bytes
let server_e_pk = KeyPair::<CS::Group>::check_public_key(Key::from_bytes( let server_e_pk = KeyPair::<CS::Group>::check_public_key(PublicKey::from_bytes(
&unchecked_server_e_pk[..KEY_LEN], &unchecked_server_e_pk[..KEY_LEN],
)?)?; )?)?;
@@ -430,12 +430,12 @@ impl<HashLen: ArrayLength<u8>> FromBytes for Ke2Message<HashLen> {
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
// The triple of public and private components used in the 3DH computation // The triple of public and private components used in the 3DH computation
struct TripleDHComponents { struct TripleDHComponents {
pk1: Key, pk1: PublicKey,
sk1: Key, sk1: PrivateKey,
pk2: Key, pk2: PublicKey,
sk2: Key, sk2: PrivateKey,
pk3: Key, pk3: PublicKey,
sk3: Key, sk3: PrivateKey,
} }
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
+81 -20
View File
@@ -37,8 +37,8 @@ impl<T> SizedBytesExt for T where T: SizedBytes {}
/// A Keypair trait with public-private verification /// A Keypair trait with public-private verification
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct KeyPair<G> { pub struct KeyPair<G> {
pk: Key, pk: PublicKey,
sk: Key, sk: PrivateKey,
_g: PhantomData<G>, _g: PhantomData<G>,
} }
@@ -58,18 +58,18 @@ impl<G> Drop for KeyPair<G> {
impl<G: Group> KeyPair<G> { impl<G: Group> KeyPair<G> {
/// The public key component /// The public key component
pub fn public(&self) -> &Key { pub fn public(&self) -> &PublicKey {
&self.pk &self.pk
} }
/// The private key component /// The private key component
pub fn private(&self) -> &Key { pub fn private(&self) -> &PrivateKey {
&self.sk &self.sk
} }
/// A constructor that receives public and private key independently as /// A constructor that receives public and private key independently as
/// bytes /// bytes
pub fn new(public: Key, private: Key) -> Result<Self, InternalPakeError> { pub fn new(public: PublicKey, private: PrivateKey) -> Result<Self, InternalPakeError> {
Ok(Self { Ok(Self {
pk: public, pk: public,
sk: private, sk: private,
@@ -83,29 +83,35 @@ impl<G: Group> KeyPair<G> {
let sk_bytes = G::scalar_as_bytes(&sk); let sk_bytes = G::scalar_as_bytes(&sk);
let pk = G::base_point().mult_by_slice(sk_bytes); let pk = G::base_point().mult_by_slice(sk_bytes);
Self { Self {
pk: Key(pk.to_arr().to_vec()), pk: PublicKey(Key(pk.to_arr().to_vec())),
sk: Key(sk_bytes.to_vec()), sk: PrivateKey(Key(sk_bytes.to_vec())),
_g: PhantomData, _g: PhantomData,
} }
} }
/// Obtaining a public key from secret bytes. At all times, we should have /// Obtaining a public key from secret bytes. At all times, we should have
/// &public_from_private(self.private()) == self.public() /// &public_from_private(self.private()) == self.public()
pub(crate) fn public_from_private(bytes: &Key) -> Key { pub(crate) fn public_from_private(bytes: &PrivateKey) -> PublicKey {
let bytes_data = GenericArray::<u8, G::ScalarLen>::from_slice(&bytes.0[..]); let bytes_data = GenericArray::<u8, G::ScalarLen>::from_slice(&bytes.0[..]);
Key(G::base_point().mult_by_slice(bytes_data).to_arr().to_vec()) PublicKey(Key(G::base_point()
.mult_by_slice(bytes_data)
.to_arr()
.to_vec()))
} }
/// Check whether a public key is valid. This is meant to be applied on /// Check whether a public key is valid. This is meant to be applied on
/// material provided through the network which fits the key /// material provided through the network which fits the key
/// representation (i.e. can be mapped to a curve point), but presents /// representation (i.e. can be mapped to a curve point), but presents
/// some risk - e.g. small subgroup check /// some risk - e.g. small subgroup check
pub(crate) fn check_public_key(key: Key) -> Result<Key, InternalPakeError> { pub(crate) fn check_public_key(key: PublicKey) -> Result<PublicKey, InternalPakeError> {
G::from_element_slice(GenericArray::from_slice(&key.0)).map(|_| key) G::from_element_slice(GenericArray::from_slice(&key.0)).map(|_| key)
} }
/// Computes the diffie hellman function on a public key and private key /// Computes the diffie hellman function on a public key and private key
pub(crate) fn diffie_hellman(pk: Key, sk: Key) -> Result<Vec<u8>, InternalPakeError> { pub(crate) fn diffie_hellman(
pk: PublicKey,
sk: PrivateKey,
) -> Result<Vec<u8>, InternalPakeError> {
let pk_data = GenericArray::<u8, G::ElemLen>::from_slice(&pk.0[..]); let pk_data = GenericArray::<u8, G::ElemLen>::from_slice(&pk.0[..]);
let point = G::from_element_slice(pk_data)?; let point = G::from_element_slice(pk_data)?;
let secret_data = GenericArray::<u8, G::ScalarLen>::from_slice(&sk.0[..]); let secret_data = GenericArray::<u8, G::ScalarLen>::from_slice(&sk.0[..]);
@@ -114,7 +120,7 @@ impl<G: Group> KeyPair<G> {
/// Obtains a KeyPair from a slice representing the private key /// Obtains a KeyPair from a slice representing the private key
pub fn from_private_key_slice(input: &[u8]) -> Result<Self, InternalPakeError> { pub fn from_private_key_slice(input: &[u8]) -> Result<Self, InternalPakeError> {
let sk = Key::from_arr(GenericArray::from_slice(input))?; let sk = PrivateKey(Key::from_arr(GenericArray::from_slice(input))?);
let pk = Self::public_from_private(&sk); let pk = Self::public_from_private(&sk);
Self::new(pk, sk) Self::new(pk, sk)
} }
@@ -122,8 +128,8 @@ impl<G: Group> KeyPair<G> {
#[cfg(test)] #[cfg(test)]
pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> { pub fn as_byte_ptrs(&self) -> Vec<(*const u8, usize)> {
vec![ vec![
(self.pk.as_ptr(), <Key as SizedBytes>::Len::to_usize()), (self.pk.as_ptr(), KeyLen::to_usize()),
(self.sk.as_ptr(), <Key as SizedBytes>::Len::to_usize()), (self.sk.as_ptr(), KeyLen::to_usize()),
] ]
} }
} }
@@ -145,6 +151,8 @@ impl<G: Group + Debug> KeyPair<G> {
} }
} }
type KeyLen = U32;
/// A minimalist key type built around a \[u8; 32\] /// A minimalist key type built around a \[u8; 32\]
#[derive(Debug, PartialEq, Eq, Clone, Zeroize)] #[derive(Debug, PartialEq, Eq, Clone, Zeroize)]
// Ensure Key material is zeroed after use. // Ensure Key material is zeroed after use.
@@ -160,18 +168,71 @@ impl Deref for Key {
} }
} }
impl SizedBytes for Key { // Don't make it implement SizedBytes so that it's not constructible outside of this module.
type Len = U32; impl Key {
fn to_arr(&self) -> GenericArray<u8, KeyLen> {
fn to_arr(&self) -> GenericArray<u8, Self::Len> {
GenericArray::clone_from_slice(&self.0[..]) GenericArray::clone_from_slice(&self.0[..])
} }
fn from_arr(key_bytes: &GenericArray<u8, Self::Len>) -> Result<Self, TryFromSizedBytesError> { fn from_arr(key_bytes: &GenericArray<u8, KeyLen>) -> Result<Self, TryFromSizedBytesError> {
Ok(Key(key_bytes.to_vec())) Ok(Key(key_bytes.to_vec()))
} }
} }
/// Wrapper around a Key to enforce that it's a private one.
#[derive(Debug, PartialEq, Eq, Clone, Zeroize)]
// Ensure Key material is zeroed after use.
#[zeroize(drop)]
#[repr(transparent)]
pub struct PrivateKey(Key);
impl Deref for PrivateKey {
type Target = Key;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl SizedBytes for PrivateKey {
type Len = KeyLen;
fn to_arr(&self) -> GenericArray<u8, Self::Len> {
self.0.to_arr()
}
fn from_arr(key_bytes: &GenericArray<u8, Self::Len>) -> Result<Self, TryFromSizedBytesError> {
Ok(PrivateKey(Key::from_arr(key_bytes)?))
}
}
/// Wrapper around a Key to enforce that it's a public one.
#[derive(Debug, PartialEq, Eq, Clone, Zeroize)]
// Ensure Key material is zeroed after use.
#[zeroize(drop)]
#[repr(transparent)]
pub struct PublicKey(Key);
impl Deref for PublicKey {
type Target = Key;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl SizedBytes for PublicKey {
type Len = KeyLen;
fn to_arr(&self) -> GenericArray<u8, Self::Len> {
self.0.to_arr()
}
fn from_arr(key_bytes: &GenericArray<u8, Self::Len>) -> Result<Self, TryFromSizedBytesError> {
Ok(PublicKey(Key::from_arr(key_bytes)?))
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@@ -183,7 +244,7 @@ mod tests {
#[test] #[test]
fn test_zeroize_key() -> Result<(), ProtocolError> { fn test_zeroize_key() -> Result<(), ProtocolError> {
let key_len = <Key as SizedBytes>::Len::to_usize(); let key_len = KeyLen::to_usize();
let mut key = Key(vec![1u8; key_len]); let mut key = Key(vec![1u8; key_len]);
let ptr = key.as_ptr(); let ptr = key.as_ptr();
+15 -14
View File
@@ -14,7 +14,7 @@ use crate::{
}, },
group::Group, group::Group,
key_exchange::traits::{FromBytes, KeyExchange, ToBytes}, key_exchange::traits::{FromBytes, KeyExchange, ToBytes},
keypair::{Key, KeyPair, SizedBytesExt}, keypair::{KeyPair, PublicKey, SizedBytesExt},
}; };
use generic_array::{typenum::Unsigned, GenericArray}; use generic_array::{typenum::Unsigned, GenericArray};
use generic_bytes::SizedBytes; use generic_bytes::SizedBytes;
@@ -61,7 +61,7 @@ pub struct RegistrationResponse<CS: CipherSuite> {
/// The server's oprf output /// The server's oprf output
pub(crate) beta: CS::Group, pub(crate) beta: CS::Group,
/// Server's static public key /// Server's static public key
pub(crate) server_s_pk: Vec<u8>, pub(crate) server_s_pk: PublicKey,
} }
// Cannot be derived because it would require for CS to be Clone. // Cannot be derived because it would require for CS to be Clone.
@@ -77,13 +77,13 @@ impl<CS: CipherSuite> Clone for RegistrationResponse<CS> {
impl<CS: CipherSuite> RegistrationResponse<CS> { impl<CS: CipherSuite> RegistrationResponse<CS> {
/// Serialization into bytes /// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
[self.beta.to_arr().to_vec(), self.server_s_pk.clone()].concat() [self.beta.to_arr().to_vec(), self.server_s_pk.to_vec()].concat()
} }
/// Deserialization from bytes /// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> { pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let elem_len = <CS::Group as Group>::ElemLen::to_usize(); let elem_len = <CS::Group as Group>::ElemLen::to_usize();
let key_len = <Key as SizedBytes>::Len::to_usize(); let key_len = <PublicKey as SizedBytes>::Len::to_usize();
let checked_slice = let checked_slice =
check_slice_size(input, elem_len + key_len, "registration_response_bytes")?; check_slice_size(input, elem_len + key_len, "registration_response_bytes")?;
@@ -91,9 +91,9 @@ impl<CS: CipherSuite> RegistrationResponse<CS> {
// correct subgroup // correct subgroup
let arr = GenericArray::from_slice(&checked_slice[..elem_len]); let arr = GenericArray::from_slice(&checked_slice[..elem_len]);
let beta = CS::Group::from_element_slice(arr)?; let beta = CS::Group::from_element_slice(arr)?;
let server_s_pk = let server_s_pk = KeyPair::<CS::Group>::check_public_key(PublicKey::from_bytes(
KeyPair::<CS::Group>::check_public_key(Key::from_bytes(&checked_slice[elem_len..])?)? &checked_slice[elem_len..],
.to_vec(); )?)?;
Ok(Self { server_s_pk, beta }) Ok(Self { server_s_pk, beta })
} }
@@ -108,7 +108,7 @@ pub struct RegistrationUpload<CS: CipherSuite> {
/// cryptographic identifiers /// cryptographic identifiers
pub(crate) envelope: Envelope<CS::Hash>, pub(crate) envelope: Envelope<CS::Hash>,
/// The user's public key /// The user's public key
pub(crate) client_s_pk: Key, pub(crate) client_s_pk: PublicKey,
} }
// Cannot be derived because it would require for CS to be Clone. // Cannot be derived because it would require for CS to be Clone.
@@ -133,7 +133,7 @@ impl<CS: CipherSuite> RegistrationUpload<CS> {
/// Deserialization from bytes /// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> { pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let key_len = <Key as SizedBytes>::Len::to_usize(); let key_len = <PublicKey as SizedBytes>::Len::to_usize();
let checked_slice = check_slice_size_atleast(input, key_len, "registration_upload_bytes")?; let checked_slice = check_slice_size_atleast(input, key_len, "registration_upload_bytes")?;
@@ -145,7 +145,7 @@ impl<CS: CipherSuite> RegistrationUpload<CS> {
Ok(Self { Ok(Self {
envelope, envelope,
client_s_pk: KeyPair::<CS::Group>::check_public_key(Key::from_bytes( client_s_pk: KeyPair::<CS::Group>::check_public_key(PublicKey::from_bytes(
&checked_slice[..key_len], &checked_slice[..key_len],
)?)?, )?)?,
}) })
@@ -204,7 +204,7 @@ impl_serialize_and_deserialize_for!(CredentialRequest);
pub struct CredentialResponse<CS: CipherSuite> { pub struct CredentialResponse<CS: CipherSuite> {
/// the server's oprf output /// the server's oprf output
pub(crate) beta: CS::Group, pub(crate) beta: CS::Group,
pub(crate) server_s_pk: Key, pub(crate) server_s_pk: PublicKey,
/// the user's sealed information, /// the user's sealed information,
pub(crate) envelope: Envelope<CS::Hash>, pub(crate) envelope: Envelope<CS::Hash>,
pub(crate) ke2_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2Message, pub(crate) ke2_message: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE2Message,
@@ -234,7 +234,7 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
pub(crate) fn serialize_without_ke( pub(crate) fn serialize_without_ke(
beta: &CS::Group, beta: &CS::Group,
server_s_pk: &Key, server_s_pk: &PublicKey,
envelope: &Envelope<CS::Hash>, envelope: &Envelope<CS::Hash>,
) -> Vec<u8> { ) -> Vec<u8> {
[ [
@@ -248,7 +248,7 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
/// Deserialization from bytes /// Deserialization from bytes
pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> { pub fn deserialize(input: &[u8]) -> Result<Self, ProtocolError> {
let elem_len = <CS::Group as Group>::ElemLen::to_usize(); let elem_len = <CS::Group as Group>::ElemLen::to_usize();
let key_len = <Key as SizedBytes>::Len::to_usize(); let key_len = <PublicKey as SizedBytes>::Len::to_usize();
let checked_slice = let checked_slice =
check_slice_size_atleast(input, elem_len + key_len, "login_second_message_bytes")?; check_slice_size_atleast(input, elem_len + key_len, "login_second_message_bytes")?;
@@ -258,7 +258,8 @@ impl<CS: CipherSuite> CredentialResponse<CS> {
let arr = GenericArray::from_slice(beta_bytes); let arr = GenericArray::from_slice(beta_bytes);
let beta = CS::Group::from_element_slice(arr)?; let beta = CS::Group::from_element_slice(arr)?;
let unchecked_server_s_pk = Key::from_bytes(&checked_slice[elem_len..elem_len + key_len])?; let unchecked_server_s_pk =
PublicKey::from_bytes(&checked_slice[elem_len..elem_len + key_len])?;
let server_s_pk = KeyPair::<CS::Group>::check_public_key(unchecked_server_s_pk)?; let server_s_pk = KeyPair::<CS::Group>::check_public_key(unchecked_server_s_pk)?;
let (envelope, remainder) = let (envelope, remainder) =
+9 -9
View File
@@ -12,7 +12,7 @@ use crate::{
group::Group, group::Group,
hash::Hash, hash::Hash,
key_exchange::traits::{FromBytes, KeyExchange, ToBytesWithPointers}, key_exchange::traits::{FromBytes, KeyExchange, ToBytesWithPointers},
keypair::{Key, KeyPair, SizedBytesExt}, keypair::{KeyPair, PrivateKey, PublicKey, SizedBytesExt},
map_to_curve::GroupWithMapToCurve, map_to_curve::GroupWithMapToCurve,
oprf, oprf,
serialization::{serialize, tokenize}, serialization::{serialize, tokenize},
@@ -275,7 +275,7 @@ impl<CS: CipherSuite> Clone for ServerRegistrationStartResult<CS> {
/// The state elements the server holds to record a registration /// The state elements the server holds to record a registration
pub struct ServerRegistration<CS: CipherSuite> { pub struct ServerRegistration<CS: CipherSuite> {
envelope: Option<Envelope<CS::Hash>>, envelope: Option<Envelope<CS::Hash>>,
client_s_pk: Option<Key>, client_s_pk: Option<PublicKey>,
pub(crate) oprf_key: <CS::Group as Group>::Scalar, pub(crate) oprf_key: <CS::Group as Group>::Scalar,
} }
@@ -315,7 +315,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
} }
// Need to do this check manually because envelope is variable-size // Need to do this check manually because envelope is variable-size
let key_len = <Key as SizedBytes>::Len::to_usize(); let key_len = <PublicKey as SizedBytes>::Len::to_usize();
let checked_bytes = let checked_bytes =
check_slice_size_atleast(input, scalar_len + key_len, "server_registration_bytes")?; check_slice_size_atleast(input, scalar_len + key_len, "server_registration_bytes")?;
@@ -323,7 +323,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
let oprf_key_bytes = GenericArray::from_slice(&checked_bytes[..scalar_len]); let oprf_key_bytes = GenericArray::from_slice(&checked_bytes[..scalar_len]);
let oprf_key = CS::Group::from_scalar_slice(oprf_key_bytes)?; let oprf_key = CS::Group::from_scalar_slice(oprf_key_bytes)?;
let unchecked_client_s_pk = let unchecked_client_s_pk =
Key::from_bytes(&checked_bytes[scalar_len..scalar_len + key_len])?; PublicKey::from_bytes(&checked_bytes[scalar_len..scalar_len + key_len])?;
let client_s_pk = KeyPair::<CS::Group>::check_public_key(unchecked_client_s_pk)?; let client_s_pk = KeyPair::<CS::Group>::check_public_key(unchecked_client_s_pk)?;
let envelope = Envelope::<CS::Hash>::from_bytes(&checked_bytes[scalar_len + key_len..])?; let envelope = Envelope::<CS::Hash>::from_bytes(&checked_bytes[scalar_len + key_len..])?;
@@ -380,7 +380,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
pub fn start<R: RngCore + CryptoRng>( pub fn start<R: RngCore + CryptoRng>(
rng: &mut R, rng: &mut R,
message: RegistrationRequest<CS>, message: RegistrationRequest<CS>,
server_s_pk: &Key, server_s_pk: &PublicKey,
) -> Result<ServerRegistrationStartResult<CS>, ProtocolError> { ) -> Result<ServerRegistrationStartResult<CS>, ProtocolError> {
// RFC: generate oprf_key (salt) and v_u = g^oprf_key // RFC: generate oprf_key (salt) and v_u = g^oprf_key
let oprf_key = CS::Group::random_scalar(rng); let oprf_key = CS::Group::random_scalar(rng);
@@ -391,7 +391,7 @@ impl<CS: CipherSuite> ServerRegistration<CS> {
Ok(ServerRegistrationStartResult { Ok(ServerRegistrationStartResult {
message: RegistrationResponse { message: RegistrationResponse {
beta, beta,
server_s_pk: server_s_pk.to_arr().to_vec(), server_s_pk: server_s_pk.clone(),
}, },
state: Self { state: Self {
envelope: None, envelope: None,
@@ -580,7 +580,7 @@ pub struct ClientLoginFinishResult<CS: CipherSuite> {
/// The client-side export key /// The client-side export key
pub export_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>, pub export_key: GenericArray<u8, <CS::Hash as Digest>::OutputSize>,
/// The server's static public key /// The server's static public key
pub server_s_pk: Key, pub server_s_pk: PublicKey,
/// The confidential info sent by the client /// The confidential info sent by the client
pub confidential_info: Vec<u8>, pub confidential_info: Vec<u8>,
/// Instance of the ClientLogin, only used in tests for checking zeroize /// Instance of the ClientLogin, only used in tests for checking zeroize
@@ -707,7 +707,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
err => PakeError::from(err), err => PakeError::from(err),
})?; })?;
let client_s_sk = Key::from_bytes(&opened_envelope.client_s_sk)?; let client_s_sk = PrivateKey::from_bytes(&opened_envelope.client_s_sk)?;
let (id_u, id_s) = match optional_ids { let (id_u, id_s) = match optional_ids {
None => ( None => (
@@ -875,7 +875,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
pub fn start<R: RngCore + CryptoRng>( pub fn start<R: RngCore + CryptoRng>(
rng: &mut R, rng: &mut R,
password_file: ServerRegistration<CS>, password_file: ServerRegistration<CS>,
server_s_sk: &Key, server_s_sk: &PrivateKey,
l1: CredentialRequest<CS>, l1: CredentialRequest<CS>,
params: ServerLoginStartParameters, params: ServerLoginStartParameters,
) -> Result<ServerLoginStartResult<CS>, ProtocolError> { ) -> Result<ServerLoginStartResult<CS>, ProtocolError> {
+3 -3
View File
@@ -10,7 +10,7 @@ use crate::{
errors::*, errors::*,
group::Group, group::Group,
key_exchange::tripledh::{NonceLen, TripleDH}, key_exchange::tripledh::{NonceLen, TripleDH},
keypair::{Key, SizedBytesExt}, keypair::{PrivateKey, PublicKey, SizedBytesExt},
opaque::*, opaque::*,
slow_hash::NoOpHash, slow_hash::NoOpHash,
tests::mock_rng::CycleRng, tests::mock_rng::CycleRng,
@@ -494,7 +494,7 @@ fn test_registration_response() -> Result<(), ProtocolError> {
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start( ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut oprf_key_rng, &mut oprf_key_rng,
RegistrationRequest::deserialize(&parameters.registration_request[..])?, RegistrationRequest::deserialize(&parameters.registration_request[..])?,
&Key::from_bytes(&parameters.server_s_pk[..])?, &PublicKey::from_bytes(&parameters.server_s_pk[..])?,
)?; )?;
assert_eq!( assert_eq!(
hex::encode(parameters.registration_response), hex::encode(parameters.registration_response),
@@ -589,7 +589,7 @@ fn test_credential_response() -> Result<(), ProtocolError> {
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start( let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_e_sk_and_nonce_rng, &mut server_e_sk_and_nonce_rng,
ServerRegistration::deserialize(&parameters.password_file[..])?, ServerRegistration::deserialize(&parameters.password_file[..])?,
&Key::from_bytes(&parameters.server_s_sk[..])?, &PrivateKey::from_bytes(&parameters.server_s_sk[..])?,
CredentialRequest::<RistrettoSha5123dhNoSlowHash>::deserialize( CredentialRequest::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.credential_request[..], &parameters.credential_request[..],
)?, )?,
+5 -5
View File
@@ -7,7 +7,7 @@ use crate::{
ciphersuite::CipherSuite, ciphersuite::CipherSuite,
errors::*, errors::*,
key_exchange::tripledh::TripleDH, key_exchange::tripledh::TripleDH,
keypair::{Key, SizedBytesExt}, keypair::{PrivateKey, PublicKey, SizedBytesExt},
opaque::*, opaque::*,
slow_hash::NoOpHash, slow_hash::NoOpHash,
tests::mock_rng::CycleRng, tests::mock_rng::CycleRng,
@@ -356,7 +356,7 @@ fn get_password_file_bytes(parameters: &TestVectorParameters) -> Result<Vec<u8>,
ServerRegistration::<Ristretto255Sha512NoSlowHash>::start( ServerRegistration::<Ristretto255Sha512NoSlowHash>::start(
&mut oprf_key_rng, &mut oprf_key_rng,
RegistrationRequest::deserialize(&parameters.registration_request[..]).unwrap(), RegistrationRequest::deserialize(&parameters.registration_request[..]).unwrap(),
&Key::from_bytes(&parameters.server_public_key[..]).unwrap(), &PublicKey::from_bytes(&parameters.server_public_key[..]).unwrap(),
)?; )?;
let password_file = server_registration_start_result let password_file = server_registration_start_result
@@ -391,7 +391,7 @@ fn test_registration_response() -> Result<(), ProtocolError> {
ServerRegistration::<Ristretto255Sha512NoSlowHash>::start( ServerRegistration::<Ristretto255Sha512NoSlowHash>::start(
&mut oprf_key_rng, &mut oprf_key_rng,
RegistrationRequest::deserialize(&parameters.registration_request[..]).unwrap(), RegistrationRequest::deserialize(&parameters.registration_request[..]).unwrap(),
&Key::from_bytes(&parameters.server_public_key[..]).unwrap(), &PublicKey::from_bytes(&parameters.server_public_key[..]).unwrap(),
)?; )?;
assert_eq!( assert_eq!(
hex::encode(parameters.registration_response), hex::encode(parameters.registration_response),
@@ -473,7 +473,7 @@ fn test_ke2() -> Result<(), ProtocolError> {
let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start( let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start(
&mut server_private_keyshare_and_nonce_rng, &mut server_private_keyshare_and_nonce_rng,
ServerRegistration::deserialize(&password_file_bytes[..]).unwrap(), ServerRegistration::deserialize(&password_file_bytes[..]).unwrap(),
&Key::from_bytes(&parameters.server_private_key[..]).unwrap(), &PrivateKey::from_bytes(&parameters.server_private_key[..]).unwrap(),
CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(&parameters.KE1[..]) CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(&parameters.KE1[..])
.unwrap(), .unwrap(),
if parameters.envelope_mode == EnvelopeMode::CustomIdentifier { if parameters.envelope_mode == EnvelopeMode::CustomIdentifier {
@@ -556,7 +556,7 @@ fn test_server_login_finish() -> Result<(), ProtocolError> {
let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start( let server_login_start_result = ServerLogin::<Ristretto255Sha512NoSlowHash>::start(
&mut server_private_keyshare_and_nonce_rng, &mut server_private_keyshare_and_nonce_rng,
ServerRegistration::deserialize(&password_file_bytes[..]).unwrap(), ServerRegistration::deserialize(&password_file_bytes[..]).unwrap(),
&Key::from_bytes(&parameters.server_private_key[..]).unwrap(), &PrivateKey::from_bytes(&parameters.server_private_key[..]).unwrap(),
CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(&parameters.KE1[..]) CredentialRequest::<Ristretto255Sha512NoSlowHash>::deserialize(&parameters.KE1[..])
.unwrap(), .unwrap(),
if parameters.envelope_mode == EnvelopeMode::CustomIdentifier { if parameters.envelope_mode == EnvelopeMode::CustomIdentifier {