surface the potential breakages out of copy_from_slice
This commit is contained in:
@@ -58,6 +58,7 @@ pub fn hash_to_point(bytes: &[u8]) -> EdwardsPoint {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Signal tests from //
|
// Signal tests from //
|
||||||
@@ -73,8 +74,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn elligator_correct() {
|
fn elligator_correct() {
|
||||||
let bytes: Vec<u8> = (0u8..32u8).collect();
|
let bytes: Vec<u8> = (0u8..32u8).collect();
|
||||||
let mut bits_in = [0u8; 32];
|
let bits_in: [u8; 32] = (&bytes[..]).try_into().expect("Range invariant broken");
|
||||||
bits_in.copy_from_slice(&bytes);
|
|
||||||
let fe = FieldElement51::from_bytes(&bits_in);
|
let fe = FieldElement51::from_bytes(&bits_in);
|
||||||
let eg = elligator_signal(&fe);
|
let eg = elligator_signal(&fe);
|
||||||
assert_eq!(eg.to_bytes(), ELLIGATOR_CORRECT_OUTPUT);
|
assert_eq!(eg.to_bytes(), ELLIGATOR_CORRECT_OUTPUT);
|
||||||
|
|||||||
+11
-6
@@ -19,6 +19,7 @@ use generic_array::{
|
|||||||
ArrayLength, GenericArray,
|
ArrayLength, GenericArray,
|
||||||
};
|
};
|
||||||
use rand_core::{CryptoRng, RngCore};
|
use rand_core::{CryptoRng, RngCore};
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
@@ -86,7 +87,8 @@ impl Group for RistrettoPoint {
|
|||||||
element_bits: &GenericArray<u8, Self::ElemLen>,
|
element_bits: &GenericArray<u8, Self::ElemLen>,
|
||||||
) -> Result<Self, InternalPakeError> {
|
) -> Result<Self, InternalPakeError> {
|
||||||
CompressedRistretto::from_slice(element_bits)
|
CompressedRistretto::from_slice(element_bits)
|
||||||
.decompress().ok_or(InternalPakeError::PointError)
|
.decompress()
|
||||||
|
.ok_or(InternalPakeError::PointError)
|
||||||
}
|
}
|
||||||
// serialization of a group element
|
// serialization of a group element
|
||||||
fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> {
|
fn to_arr(&self) -> GenericArray<u8, Self::ElemLen> {
|
||||||
@@ -96,8 +98,9 @@ impl Group for RistrettoPoint {
|
|||||||
|
|
||||||
type UniformBytesLen = U64;
|
type UniformBytesLen = U64;
|
||||||
fn hash_to_curve(uniform_bytes: &GenericArray<u8, Self::UniformBytesLen>) -> Self {
|
fn hash_to_curve(uniform_bytes: &GenericArray<u8, Self::UniformBytesLen>) -> Self {
|
||||||
let mut bits = [0u8; 64];
|
let bits: [u8; 64] = (&uniform_bytes[..])
|
||||||
bits.copy_from_slice(&uniform_bytes);
|
.try_into()
|
||||||
|
.expect("GenericArray has a type-level length");
|
||||||
|
|
||||||
RistrettoPoint::from_uniform_bytes(&bits)
|
RistrettoPoint::from_uniform_bytes(&bits)
|
||||||
}
|
}
|
||||||
@@ -130,7 +133,8 @@ impl Group for EdwardsPoint {
|
|||||||
element_bits: &GenericArray<u8, Self::ElemLen>,
|
element_bits: &GenericArray<u8, Self::ElemLen>,
|
||||||
) -> Result<Self, InternalPakeError> {
|
) -> Result<Self, InternalPakeError> {
|
||||||
let point = CompressedEdwardsY::from_slice(element_bits)
|
let point = CompressedEdwardsY::from_slice(element_bits)
|
||||||
.decompress().ok_or(InternalPakeError::PointError)?;
|
.decompress()
|
||||||
|
.ok_or(InternalPakeError::PointError)?;
|
||||||
|
|
||||||
if point.is_small_order() {
|
if point.is_small_order() {
|
||||||
return Err(InternalPakeError::SubGroupError);
|
return Err(InternalPakeError::SubGroupError);
|
||||||
@@ -190,8 +194,9 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
fn deserialize_point(pt: &[u8]) -> Result<EdwardsPoint> {
|
fn deserialize_point(pt: &[u8]) -> Result<EdwardsPoint> {
|
||||||
let mut bytes = [0u8; 32];
|
let bytes: [u8; 32] = (&pt[..32])
|
||||||
bytes.copy_from_slice(&pt[..32]);
|
.try_into()
|
||||||
|
.expect("Slice pattern invariant broken");
|
||||||
|
|
||||||
curve25519_dalek::edwards::CompressedEdwardsY(bytes)
|
curve25519_dalek::edwards::CompressedEdwardsY(bytes)
|
||||||
.decompress()
|
.decompress()
|
||||||
|
|||||||
+5
-4
@@ -16,6 +16,7 @@ use proptest::prelude::*;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use rand::{rngs::StdRng, SeedableRng};
|
use rand::{rngs::StdRng, SeedableRng};
|
||||||
use rand_core::{CryptoRng, RngCore};
|
use rand_core::{CryptoRng, RngCore};
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use x25519_dalek::{PublicKey, StaticSecret};
|
use x25519_dalek::{PublicKey, StaticSecret};
|
||||||
|
|
||||||
@@ -216,15 +217,15 @@ impl KeyPair for X25519KeyPair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn public_from_private(secret: &Self::Repr) -> Self::Repr {
|
fn public_from_private(secret: &Self::Repr) -> Self::Repr {
|
||||||
let mut secret_data = [0u8; 32];
|
let secret_data: [u8; 32] = (&secret.0[..])
|
||||||
secret_data.copy_from_slice(&secret.0[..]);
|
.try_into()
|
||||||
|
.expect("Keypair::Repr invariant broken");
|
||||||
let base_data = ::x25519_dalek::X25519_BASEPOINT_BYTES;
|
let base_data = ::x25519_dalek::X25519_BASEPOINT_BYTES;
|
||||||
Key(::x25519_dalek::x25519(secret_data, base_data).to_vec())
|
Key(::x25519_dalek::x25519(secret_data, base_data).to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_public_key(key: Self::Repr) -> Result<Self::Repr, InternalPakeError> {
|
fn check_public_key(key: Self::Repr) -> Result<Self::Repr, InternalPakeError> {
|
||||||
let mut key_bytes = [0u8; 32];
|
let key_bytes: [u8; 32] = (&key[..]).try_into().expect("Key invariant broken");
|
||||||
key_bytes.copy_from_slice(&key);
|
|
||||||
let point = ::curve25519_dalek::montgomery::MontgomeryPoint(key_bytes)
|
let point = ::curve25519_dalek::montgomery::MontgomeryPoint(key_bytes)
|
||||||
.to_edwards(1)
|
.to_edwards(1)
|
||||||
.ok_or(InternalPakeError::PointError)?;
|
.ok_or(InternalPakeError::PointError)?;
|
||||||
|
|||||||
+6
-13
@@ -533,14 +533,12 @@ where
|
|||||||
/// byte representation for the server's registration state
|
/// byte representation for the server's registration state
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
let mut output: Vec<u8> = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec();
|
let mut output: Vec<u8> = CS::Group::scalar_as_bytes(&self.oprf_key).to_vec();
|
||||||
match &self.client_s_pk {
|
self.client_s_pk
|
||||||
Some(v) => output.extend_from_slice(&v.to_arr()),
|
.iter()
|
||||||
None => {}
|
.for_each(|v| output.extend_from_slice(&v));
|
||||||
};
|
self.envelope
|
||||||
match &self.envelope {
|
.iter()
|
||||||
Some(v) => output.extend_from_slice(&v.to_bytes()),
|
.for_each(|v| output.extend_from_slice(&v.to_bytes()));
|
||||||
None => {}
|
|
||||||
};
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,8 +639,6 @@ where
|
|||||||
|
|
||||||
/// The state elements the client holds to perform a login
|
/// The state elements the client holds to perform a login
|
||||||
pub struct ClientLogin<CS: CipherSuite> {
|
pub struct ClientLogin<CS: CipherSuite> {
|
||||||
/// A choice of the keypair type
|
|
||||||
_key_format: PhantomData<CS::KeyFormat>,
|
|
||||||
/// A blinding factor, which is used to mask (and unmask) secret
|
/// A blinding factor, which is used to mask (and unmask) secret
|
||||||
/// information before transmission
|
/// information before transmission
|
||||||
blinding_factor: <CS::Group as Group>::Scalar,
|
blinding_factor: <CS::Group as Group>::Scalar,
|
||||||
@@ -675,7 +671,6 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for ClientLogin<CS> {
|
|||||||
)?;
|
)?;
|
||||||
let password = bytes[scalar_len + ke1_state_size..].to_vec();
|
let password = bytes[scalar_len + ke1_state_size..].to_vec();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
_key_format: PhantomData,
|
|
||||||
blinding_factor,
|
blinding_factor,
|
||||||
password,
|
password,
|
||||||
ke1_state,
|
ke1_state,
|
||||||
@@ -745,7 +740,6 @@ impl<CS: CipherSuite> ClientLogin<CS> {
|
|||||||
Ok((
|
Ok((
|
||||||
l1,
|
l1,
|
||||||
Self {
|
Self {
|
||||||
_key_format: PhantomData,
|
|
||||||
blinding_factor,
|
blinding_factor,
|
||||||
password: password.to_vec(),
|
password: password.to_vec(),
|
||||||
ke1_state,
|
ke1_state,
|
||||||
@@ -986,7 +980,6 @@ impl<CS: CipherSuite> ServerLogin<CS> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
|
|
||||||
fn get_password_derived_key<G: Group, SH: SlowHash<D>, D: Hash>(
|
fn get_password_derived_key<G: Group, SH: SlowHash<D>, D: Hash>(
|
||||||
password: Vec<u8>,
|
password: Vec<u8>,
|
||||||
beta: G,
|
beta: G,
|
||||||
|
|||||||
@@ -558,7 +558,12 @@ fn test_complete_flow(
|
|||||||
hex::encode(login_export_key)
|
hex::encode(login_export_key)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let res = matches!(client_login_result, Err(ProtocolError::VerificationError(PakeError::InvalidLoginError)));
|
let res = matches!(
|
||||||
|
client_login_result,
|
||||||
|
Err(ProtocolError::VerificationError(
|
||||||
|
PakeError::InvalidLoginError
|
||||||
|
))
|
||||||
|
);
|
||||||
assert!(res);
|
assert!(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user