Addressing various TODOs and minor cleanups (#127)

This commit is contained in:
Kevin Lewi
2021-02-02 12:12:20 -08:00
committed by GitHub
parent be6d042d80
commit 9d3963f98e
12 changed files with 120 additions and 135 deletions
Generated
-46
View File
@@ -389,12 +389,6 @@ version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
[[package]]
name = "fiat-crypto"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f6ab97095615857b6ad00a8330fff0e443f1def9fd357cef82d0ca0677b616b"
[[package]]
name = "fnv"
version = "1.0.7"
@@ -613,7 +607,6 @@ dependencies = [
"curve25519-dalek",
"digest",
"displaydoc",
"fiat-crypto",
"generic-array",
"generic-bytes",
"generic-bytes-derive",
@@ -630,7 +623,6 @@ dependencies = [
"sha2",
"subtle",
"thiserror",
"x25519-dalek",
"zeroize",
]
@@ -1023,18 +1015,6 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "synstructure"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]]
name = "tempfile"
version = "3.1.0"
@@ -1255,34 +1235,8 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "x25519-dalek"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc614d95359fd7afc321b66d2107ede58b246b844cf5d8a0adcca413e439f088"
dependencies = [
"curve25519-dalek",
"rand_core",
"zeroize",
]
[[package]]
name = "zeroize"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f33972566adbd2d3588b0491eb94b98b43695c4ef897903470ede4f3f5a28a"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
+3 -5
View File
@@ -13,14 +13,13 @@ readme = "README.md"
default = ["u64_backend"]
slow-hash = ["scrypt"]
bench = []
u64_backend = ["curve25519-dalek/u64_backend", "x25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend", "x25519-dalek/u32_backend"]
u64_backend = ["curve25519-dalek/u64_backend"]
u32_backend = ["curve25519-dalek/u32_backend"]
[dependencies]
curve25519-dalek = { version = "3.0.0", default-features = false, features = ["std"] }
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" }
@@ -28,10 +27,8 @@ hkdf = "0.10.0"
hmac = "0.10.1"
rand_core = "0.5.1"
scrypt = { version = "0.5.0", optional = true }
sha2 = "0.9.2"
subtle = { version = "2.3.0", default-features = false }
thiserror = "1.0.22"
x25519-dalek = { version = "1.1.0", default-features = false, features = ["std"] }
zeroize = "1.1.1"
[dev-dependencies]
@@ -42,6 +39,7 @@ criterion = "0.3.3"
hex = "0.4.2"
lazy_static = "1.4.0"
serde_json = "1.0.60"
sha2 = "0.9.2"
proptest = "0.10.1"
rand = "0.7"
rustyline = "7.0.0"
+23 -5
View File
@@ -34,9 +34,9 @@ use std::process::exit;
use opaque_ke::{
ciphersuite::CipherSuite, ClientLogin, ClientLoginFinishParameters, ClientLoginStartParameters,
ClientRegistration, ClientRegistrationFinishParameters, CredentialRequest, CredentialResponse,
RegistrationRequest, RegistrationResponse, RegistrationUpload, ServerLogin,
ServerLoginStartParameters, ServerRegistration,
ClientRegistration, ClientRegistrationFinishParameters, CredentialFinalization,
CredentialRequest, CredentialResponse, RegistrationRequest, RegistrationResponse,
RegistrationUpload, ServerLogin, ServerLoginStartParameters, ServerRegistration,
};
// The ciphersuite trait allows to specify the underlying primitives
@@ -173,9 +173,27 @@ fn open_locker(
return Err(String::from("Incorrect password, please try again."));
}
let client_login_finish_result = result.unwrap();
let credential_finalization_bytes = client_login_finish_result.message.serialize();
// Decrypt contents of locker
let plaintext = decrypt(&client_login_finish_result.export_key, &locker.contents);
// Client sends credential_finalization_bytes to server
let server_login_finish_result = server_login_start_result
.state
.finish(CredentialFinalization::deserialize(&credential_finalization_bytes[..]).unwrap())
.unwrap();
// Server sends locker contents, encrypted under the session key, to the client
let encrypted_locker_contents =
encrypt(&server_login_finish_result.shared_secret, &locker.contents);
// Client decrypts contents of locker, first under the shared secret, and then under the export key
let plaintext = decrypt(
&client_login_finish_result.export_key,
&decrypt(
&client_login_finish_result.shared_secret,
&encrypted_locker_contents,
),
);
String::from_utf8(plaintext).map_err(|_| String::from("UTF8 error"))
}
+3
View File
@@ -100,6 +100,9 @@ pub(crate) struct Envelope<D: Hash> {
hmac: GenericArray<u8, <D as Digest>::OutputSize>,
}
// Note that this struct represents an envelope that has been "opened" with the asssociated
// key. This key is also used to derive the export_key parameter, which is technically
// unrelated to the envelope's encrypted and authenticated contents.
pub(crate) struct OpenedEnvelope<D: Hash> {
pub(crate) client_s_sk: Vec<u8>,
pub(crate) export_key: GenericArray<u8, <D as Digest>::OutputSize>,
+1 -1
View File
@@ -21,7 +21,6 @@ pub trait KeyExchange<D: Hash, G: Group> {
type KE3Message: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytes;
fn generate_ke1<R: RngCore + CryptoRng>(
l1_component: Vec<u8>,
info: Vec<u8>,
rng: &mut R,
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>;
@@ -44,6 +43,7 @@ pub trait KeyExchange<D: Hash, G: Group> {
l2_component: Vec<u8>,
ke2_message: Self::KE2Message,
ke1_state: &Self::KE1State,
serialized_credential_request: &[u8],
server_s_pk: Key,
client_s_sk: Key,
id_u: Vec<u8>,
+19 -28
View File
@@ -28,7 +28,6 @@ use rand_core::{CryptoRng, RngCore};
use std::convert::TryFrom;
const KEY_LEN: usize = 32;
pub(crate) const NONCE_LEN: usize = 32;
pub(crate) type NonceLen = U32;
static STR_3DH: &[u8] = b"3DH keys";
@@ -51,15 +50,14 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
type KE3Message = KE3Message<<D as FixedOutput>::OutputSize>;
fn generate_ke1<R: RngCore + CryptoRng>(
alpha_bytes: Vec<u8>,
info: Vec<u8>,
rng: &mut R,
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> {
let client_e_kp = KeyPair::<G>::generate_random(rng);
let client_nonce: GenericArray<u8, NonceLen> = {
let mut client_nonce_bytes = [0u8; NONCE_LEN];
let mut client_nonce_bytes = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut client_nonce_bytes);
client_nonce_bytes.into()
GenericArray::clone_from_slice(&client_nonce_bytes)
};
let ke1_message = KE1Message {
@@ -68,14 +66,10 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
client_e_pk: client_e_kp.public().clone(),
};
// TODO: must match the serialization of a credential request, could be done more cleanly
let serialized_credential_request = [alpha_bytes, ke1_message.to_bytes()].concat();
Ok((
KE1State {
client_e_sk: client_e_kp.private().clone(),
client_nonce,
serialized_credential_request,
},
ke1_message,
))
@@ -95,9 +89,9 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
) -> Result<(Vec<u8>, Self::KE2State, Self::KE2Message), ProtocolError> {
let server_e_kp = KeyPair::<G>::generate_random(rng);
let server_nonce: GenericArray<u8, NonceLen> = {
let mut server_nonce_bytes = [0u8; NONCE_LEN];
let mut server_nonce_bytes = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut server_nonce_bytes);
server_nonce_bytes.into()
GenericArray::clone_from_slice(&server_nonce_bytes)
};
let (session_secret, km2, ke2, km3) = derive_3dh_keys::<D, G>(
@@ -169,6 +163,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
l2_component: Vec<u8>,
ke2_message: Self::KE2Message,
ke1_state: &Self::KE1State,
serialized_credential_request: &[u8],
server_s_pk: Key,
client_s_sk: Key,
id_u: Vec<u8>,
@@ -190,7 +185,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
)?;
let transcript: Vec<u8> = [
&ke1_state.serialized_credential_request[..],
&serialized_credential_request,
&l2_component[..],
&ke2_message.to_bytes_without_mac(),
]
@@ -258,7 +253,7 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
}
fn ke2_message_size() -> usize {
NONCE_LEN + KEY_LEN + <<D as FixedOutput>::OutputSize as Unsigned>::to_usize()
NonceLen::to_usize() + KEY_LEN + <<D as FixedOutput>::OutputSize as Unsigned>::to_usize()
}
}
@@ -267,7 +262,6 @@ impl<D: Hash, G: Group> KeyExchange<D, G> for TripleDH {
pub struct KE1State {
client_e_sk: Key,
client_nonce: GenericArray<u8, NonceLen>,
serialized_credential_request: Vec<u8>,
}
/// The first key exchange message
@@ -282,26 +276,21 @@ impl TryFrom<&[u8]> for KE1State {
type Error = PakeError;
fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
let checked_bytes = check_slice_size_atleast(bytes, KEY_LEN + NONCE_LEN, "ke1_state")?;
let nonce_len = NonceLen::to_usize();
let checked_bytes = check_slice_size_atleast(bytes, KEY_LEN + nonce_len, "ke1_state")?;
Ok(Self {
client_e_sk: Key::from_bytes(&checked_bytes[..KEY_LEN])?,
client_nonce: GenericArray::clone_from_slice(
&checked_bytes[KEY_LEN..KEY_LEN + NONCE_LEN],
&checked_bytes[KEY_LEN..KEY_LEN + nonce_len],
),
serialized_credential_request: checked_bytes[KEY_LEN + NONCE_LEN..].to_vec(),
})
}
}
impl ToBytes for KE1State {
fn to_bytes(&self) -> Vec<u8> {
let output: Vec<u8> = [
&self.client_e_sk.to_arr(),
&self.client_nonce[..],
&self.serialized_credential_request[..],
]
.concat();
let output: Vec<u8> = [&self.client_e_sk.to_arr(), &self.client_nonce[..]].concat();
output
}
}
@@ -321,15 +310,16 @@ impl TryFrom<&[u8]> for KE1Message {
type Error = PakeError;
fn try_from(ke1_message_bytes: &[u8]) -> Result<Self, Self::Error> {
let nonce_len = NonceLen::to_usize();
let checked_nonce =
check_slice_size_atleast(ke1_message_bytes, NONCE_LEN, "ke1_message nonce")?;
check_slice_size_atleast(ke1_message_bytes, nonce_len, "ke1_message nonce")?;
let (info, remainder) = tokenize(&checked_nonce[NONCE_LEN..], 2)?;
let (info, remainder) = tokenize(&checked_nonce[nonce_len..], 2)?;
let checked_client_e_pk = check_slice_size(&remainder, KEY_LEN, "ke1_message client_e_pk")?;
Ok(Self {
client_nonce: GenericArray::clone_from_slice(&checked_nonce[..NONCE_LEN]),
client_nonce: GenericArray::clone_from_slice(&checked_nonce[..nonce_len]),
info,
client_e_pk: Key::from_bytes(&checked_client_e_pk)?,
})
@@ -401,9 +391,10 @@ impl<HashLen: ArrayLength<u8>> TryFrom<&[u8]> for KE2Message<HashLen> {
type Error = PakeError;
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
let checked_nonce = check_slice_size_atleast(input, NONCE_LEN, "ke2_message nonce")?;
let nonce_len = NonceLen::to_usize();
let checked_nonce = check_slice_size_atleast(input, nonce_len, "ke2_message nonce")?;
let checked_server_e_pk = check_slice_size_atleast(
&checked_nonce[NONCE_LEN..],
&checked_nonce[nonce_len..],
KEY_LEN,
"ke2_message server_e_pk",
)?;
@@ -411,7 +402,7 @@ impl<HashLen: ArrayLength<u8>> TryFrom<&[u8]> for KE2Message<HashLen> {
let checked_mac = check_slice_size(&remainder, HashLen::to_usize(), "ke1_message mac")?;
Ok(Self {
server_nonce: GenericArray::clone_from_slice(&checked_nonce[..NONCE_LEN]),
server_nonce: GenericArray::clone_from_slice(&checked_nonce[..nonce_len]),
server_e_pk: Key::from_bytes(&checked_server_e_pk[..KEY_LEN])?,
e_info,
mac: GenericArray::clone_from_slice(&checked_mac),
-1
View File
@@ -37,7 +37,6 @@ impl GroupWithMapToCurve for RistrettoPoint {
// Implements the hash_to_ristretto255() function from
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt
fn map_to_curve<H: Hash>(msg: &[u8], dst: &[u8]) -> Result<Self, InternalPakeError> {
// FIXME use generic_array and turn this into a compile-time error if size mismatch
let uniform_bytes =
expand_message_xmd::<H>(msg, dst, <H as Digest>::OutputSize::to_usize())?;
Ok(<Self as Group>::hash_to_curve(
+18 -6
View File
@@ -259,12 +259,24 @@ pub struct CredentialResponse<CS: CipherSuite> {
impl<CS: CipherSuite> CredentialResponse<CS> {
/// Serialization into bytes
pub fn serialize(&self) -> Vec<u8> {
let mut credential_response: Vec<u8> = Vec::new();
credential_response.extend_from_slice(&self.beta.to_arr());
credential_response.extend_from_slice(&serialize(&self.server_s_pk.to_arr().to_vec(), 2));
credential_response.extend_from_slice(&self.envelope.to_bytes());
credential_response.extend_from_slice(&self.ke2_message.to_bytes());
credential_response
[
Self::serialize_without_ke(&self.beta, &self.server_s_pk, &self.envelope),
self.ke2_message.to_bytes(),
]
.concat()
}
pub(crate) fn serialize_without_ke(
beta: &CS::Group,
server_s_pk: &Key,
envelope: &Envelope<CS::Hash>,
) -> Vec<u8> {
[
&beta.to_arr(),
&serialize(&server_s_pk.to_arr().to_vec(), 2)[..],
&envelope.to_bytes(),
]
.concat()
}
/// Deserialization from bytes
+20 -17
View File
@@ -408,6 +408,7 @@ pub struct ClientLogin<CS: CipherSuite> {
/// token containing the client's password and the blinding factor
token: oprf::Token<CS::Group>,
ke1_state: <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State,
serialized_credential_request: Vec<u8>,
}
impl<CS: CipherSuite> TryFrom<&[u8]> for ClientLogin<CS> {
@@ -427,7 +428,8 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for ClientLogin<CS> {
let blinding_factor_bytes = GenericArray::from_slice(&checked_slice[..scalar_len]);
let blinding_factor = CS::Group::from_scalar_slice(blinding_factor_bytes)?;
let (ke1_state_bytes, password) = tokenize(&checked_slice[scalar_len..], 2)?;
let (serialized_credential_request, remainder) = tokenize(&checked_slice[scalar_len..], 2)?;
let (ke1_state_bytes, password) = tokenize(&remainder, 2)?;
let ke1_state = <CS::KeyExchange as KeyExchange<CS::Hash, CS::Group>>::KE1State::try_from(
&ke1_state_bytes[..],
@@ -438,6 +440,7 @@ impl<CS: CipherSuite> TryFrom<&[u8]> for ClientLogin<CS> {
blind: blinding_factor,
},
ke1_state,
serialized_credential_request,
})
}
}
@@ -447,6 +450,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
pub fn to_bytes(&self) -> Vec<u8> {
let output: Vec<u8> = [
&CS::Group::scalar_as_bytes(&self.token.blind)[..],
&serialize(&self.serialized_credential_request, 2),
&serialize(&self.ke1_state.to_bytes(), 2),
&self.token.data,
]
@@ -536,14 +540,18 @@ impl<CS: CipherSuite> ClientLogin<CS> {
let (token, alpha) = oprf::blind::<R, CS::Group, CS::Hash>(&password, rng)?;
let (ke1_state, ke1_message) =
CS::KeyExchange::generate_ke1(alpha.to_arr().to_vec(), info, rng)?;
let (ke1_state, ke1_message) = CS::KeyExchange::generate_ke1(info, rng)?;
let l1 = CredentialRequest { alpha, ke1_message };
let credential_request = CredentialRequest { alpha, ke1_message };
let serialized_credential_request = credential_request.serialize();
Ok(ClientLoginStartResult {
message: l1,
state: Self { token, ke1_state },
message: credential_request,
state: Self {
token,
ke1_state,
serialized_credential_request,
},
})
}
@@ -627,6 +635,7 @@ impl<CS: CipherSuite> ClientLogin<CS> {
l2_bytes,
l2.ke2_message,
&self.ke1_state,
&self.serialized_credential_request,
l2.server_s_pk.clone(),
client_s_sk,
id_u,
@@ -772,21 +781,15 @@ impl<CS: CipherSuite> ServerLogin<CS> {
let l1_bytes = &l1.to_bytes();
let beta = oprf::evaluate(l1.alpha, &password_file.oprf_key);
let server_s_pk = KeyPair::<CS::Group>::public_from_private(&server_s_sk);
// TODO: must match serialization of credential response, could be done more cleanly
let l2_component: Vec<u8> = [
&beta.to_arr()[..],
&serialize(&server_s_pk.to_arr()[..], 2),
&envelope.to_bytes()[..],
]
.concat();
let credential_response_component =
CredentialResponse::<CS>::serialize_without_ke(&beta, &server_s_pk, &envelope);
let (plain_info, ke2_state, ke2_message) = CS::KeyExchange::generate_ke2(
rng,
l1_bytes.to_vec(),
l2_component,
credential_response_component,
l1.ke1_message,
client_s_pk,
server_s_sk.clone(),
@@ -795,7 +798,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
e_info,
)?;
let l2 = CredentialResponse {
let credential_response = CredentialResponse {
beta,
server_s_pk,
envelope,
@@ -804,7 +807,7 @@ impl<CS: CipherSuite> ServerLogin<CS> {
Ok(ServerLoginStartResult {
plain_info,
message: l2,
message: credential_response,
state: Self {
_cs: PhantomData,
ke2_state,
-1
View File
@@ -22,7 +22,6 @@ pub(crate) fn i2osp(input: usize, length: usize) -> Vec<u8> {
// Corresponds to the OS2IP() function from RFC8017
pub(crate) fn os2ip(input: &[u8]) -> Result<usize, PakeError> {
if input.len() > std::mem::size_of::<usize>() {
// TODO:: check RFC compliance in refusing this
return Err(PakeError::SerializationError);
}
+18 -10
View File
@@ -9,7 +9,7 @@ use crate::{
group::Group,
key_exchange::{
traits::{KeyExchange, ToBytes},
tripledh::{TripleDH, NONCE_LEN},
tripledh::{NonceLen, TripleDH},
},
opaque::*,
serialization::{i2osp, os2ip, serialize},
@@ -17,6 +17,7 @@ use crate::{
};
use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned;
use generic_bytes::SizedBytes;
use proptest::{collection::vec, prelude::*};
use rand_core::{OsRng, RngCore};
@@ -79,7 +80,7 @@ fn server_registration_roundtrip() {
// Construct a mock envelope
let mut mock_envelope_bytes = Vec::new();
mock_envelope_bytes.extend_from_slice(&[0; 1]); // mode = 0
mock_envelope_bytes.extend_from_slice(&[0; NONCE_LEN]); // empty nonce
mock_envelope_bytes.extend_from_slice(&vec![0; NonceLen::to_usize()]); // empty nonce
mock_envelope_bytes.extend_from_slice(&[0, 0]); // empty ciphertext
mock_envelope_bytes.extend_from_slice(&[0; MAC_SIZE]); // length-MAC_SIZE hmac
@@ -168,7 +169,7 @@ fn login_first_message_roundtrip() {
let alpha_bytes = alpha.to_arr().to_vec();
let client_e_kp = Default::generate_random_keypair(&mut rng);
let mut client_nonce = [0u8; NONCE_LEN];
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut client_nonce);
let mut info = [0u8; MAX_INFO_LENGTH];
@@ -218,7 +219,7 @@ fn login_second_message_roundtrip() {
let server_e_kp = Default::generate_random_keypair(&mut rng);
let mut mac = [0u8; MAC_SIZE];
rng.fill_bytes(&mut mac);
let mut server_nonce = [0u8; NONCE_LEN];
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut server_nonce);
let mut e_info = [0u8; MAX_INFO_LENGTH];
@@ -264,13 +265,20 @@ fn client_login_roundtrip() {
let sc = <RistrettoPoint as Group>::random_scalar(&mut rng);
let client_e_kp = Default::generate_random_keypair(&mut rng);
let mut client_nonce = [0u8; NONCE_LEN];
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut client_nonce);
let l1_data = [&sc.to_bytes()[..], &client_nonce, client_e_kp.public()].concat();
let serialized_credential_request = b"serialized credential_request".to_vec();
let l1_data = [client_e_kp.private().to_arr().to_vec(), client_nonce].concat();
// serialization order: scalar, password, ke1_state
let bytes: Vec<u8> = [&sc.as_bytes()[..], &serialize(&l1_data, 2), &pw[..]].concat();
// serialization order: scalar, credential_request, ke1_state, password
let bytes: Vec<u8> = [
&sc.as_bytes()[..],
&serialize(&serialized_credential_request, 2),
&serialize(&l1_data, 2),
&pw[..],
]
.concat();
let reg = ClientLogin::<Default>::try_from(&bytes[..]).unwrap();
let reg_bytes = reg.to_bytes();
assert_eq!(reg_bytes, bytes);
@@ -281,7 +289,7 @@ fn ke1_message_roundtrip() {
let mut rng = OsRng;
let client_e_kp = Default::generate_random_keypair(&mut rng);
let mut client_nonce = [0u8; NONCE_LEN];
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut client_nonce);
let mut info = [0u8; MAX_INFO_LENGTH];
@@ -307,7 +315,7 @@ fn ke2_message_roundtrip() {
let server_e_kp = Default::generate_random_keypair(&mut rng);
let mut mac = [0u8; MAC_SIZE];
rng.fill_bytes(&mut mac);
let mut server_nonce = [0u8; NONCE_LEN];
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut server_nonce);
let mut e_info = [0u8; MAX_INFO_LENGTH];
rng.fill_bytes(&mut e_info);
+15 -15
View File
@@ -7,7 +7,7 @@ use crate::{
ciphersuite::CipherSuite,
errors::*,
group::Group,
key_exchange::tripledh::{TripleDH, NONCE_LEN},
key_exchange::tripledh::{NonceLen, TripleDH},
keypair::Key,
opaque::*,
slow_hash::NoOpHash,
@@ -15,6 +15,7 @@ use crate::{
*,
};
use curve25519_dalek::ristretto::RistrettoPoint;
use generic_array::typenum::Unsigned;
use generic_bytes::SizedBytes;
use rand_core::{OsRng, RngCore};
use serde_json::Value;
@@ -92,7 +93,7 @@ static TEST_VECTOR: &str = r#"
"credential_response": "2e9bf80e5c101ee2d391ff2aec06af97af17f443fc93a5cc98189681cb943d700020b67d948b98eecfb516a626fab94170e490ccd90da05fce94a016c4d5d6b7136a015dba53e994e82b6d76353341102791cdfb1c2b460e1f913c5741a9c8cf2017c90022f11b89b207eb0735f2bdb2a9968bc9d7c1c962fd0274b4fc1fff2466c769d3710586a3a21ac8ecf13aafe2dc5460eb2f52d8f760396a17beeaf1ef3d1e4e50dd906555832fc51fc474554cb9ff063f6685f9043efc08fd6816666833d68d3b0eb6d913cc5ceb7687d80293005e7f9452ce104d1bac6598dd2265f184cacd558d6b3142103d44b03f3886fe3e419b1b96521fa5a706bb1a4e003907daa381960d664a0006a0f4de671e13c37b24e29138ff9d3df3d55c3b822fedee8dcefd643a1deab7cda5aa1c20f31a0c2a1823c8de3e793f50b257833788b75609fb6c5c4a9cad225f3a981c4ff7b2",
"credential_finalization": "0640114ec21fbad6da11c61dfa77a48026646a2a1bd091ef5c9dc46b45f9e53c72f5d714e026d808b6de8911947eef437e9f6a6e969e1ea13f2f4880adc7c879",
"client_registration_state": "a70b37951d84ed312a0a8e025b71eafdd362b4e7db872881762d506a271b6e0770617373776f7264",
"client_login_state": "a70b37951d84ed312a0a8e025b71eafdd362b4e7db872881762d506a271b6e0700a728fb3aadbc2716844d8de562d35e61914da734dcea0fa6ebd79603ef9eff4e01488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4cecf819ef83351e4c75e016ef845b62a12c14f397328960574935a42e04e0fa42488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4c0005696e666f3108973113b27d6f2291aaaeb92f34a8438d279a48b1b412bddbf2785be660e47970617373776f7264",
"client_login_state": "a70b37951d84ed312a0a8e025b71eafdd362b4e7db872881762d506a271b6e070067ecf819ef83351e4c75e016ef845b62a12c14f397328960574935a42e04e0fa42488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4c0005696e666f3108973113b27d6f2291aaaeb92f34a8438d279a48b1b412bddbf2785be660e479004028fb3aadbc2716844d8de562d35e61914da734dcea0fa6ebd79603ef9eff4e01488244dbf75f86ebaa30307773d3e0eabccb91be349abef8a69c458dbf236e4c70617373776f7264",
"server_registration_state": "1eaf3cdd64da67e17e3364182f00ed0c323bfb44b20a1b7e0025a0334ab6d40d",
"server_login_state": "4952acf61167e6d0e799572827724fdf8c80bda8c62ac28deb68d125661dade2cc1136e634d5fb93f1de4d170ae3e2f5885e333ac3b72d630ab56618c2247fa4d5968eefd69cd270ed14fbcb39627fea9a93cd18175e1b5cfceb06f705bbcb5ecddcd0602aacd7cb358f3273b1099895210bf8baa37d2fab5ed8c092fe9e5739bc6c50cf08ca7d4f4107d48057507480e0c9534b4f04d77cd5156cbd112565d8a2d5beaa473003dcf8dd82d4046648a701c72afeed0f627fcb782627dfaed3ca",
"password_file": "1eaf3cdd64da67e17e3364182f00ed0c323bfb44b20a1b7e0025a0334ab6d40dba8c7e239ed64ea1e6068b52cbd5a34ba6f55d635d20a4593884dc271865ea63015dba53e994e82b6d76353341102791cdfb1c2b460e1f913c5741a9c8cf2017c90022f11b89b207eb0735f2bdb2a9968bc9d7c1c962fd0274b4fc1fff2466c769d3710586a3a21ac8ecf13aafe2dc5460eb2f52d8f760396a17beeaf1ef3d1e4e50dd906555832fc51fc474554cb9ff063f6685f9043efc08fd6816666833d68d3b0eb6d9",
@@ -274,9 +275,9 @@ fn generate_parameters<CS: CipherSuite>() -> TestVectorParameters {
rng.fill_bytes(&mut oprf_key_raw);
let mut envelope_nonce = [0u8; 32];
rng.fill_bytes(&mut envelope_nonce);
let mut client_nonce = [0u8; NONCE_LEN];
let mut client_nonce = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut client_nonce);
let mut server_nonce = [0u8; NONCE_LEN];
let mut server_nonce = vec![0u8; NonceLen::to_usize()];
rng.fill_bytes(&mut server_nonce);
let blinding_factor = CS::Group::random_scalar(&mut rng);
@@ -451,8 +452,8 @@ fn test_registration_response() -> Result<(), ProtocolError> {
let server_registration_start_result =
ServerRegistration::<RistrettoSha5123dhNoSlowHash>::start(
&mut oprf_key_rng,
RegistrationRequest::deserialize(&parameters.registration_request[..]).unwrap(),
&Key::try_from(&parameters.server_s_pk[..]).unwrap(),
RegistrationRequest::deserialize(&parameters.registration_request[..])?,
&Key::try_from(&parameters.server_s_pk[..])?,
)?;
assert_eq!(
hex::encode(parameters.registration_response),
@@ -477,7 +478,7 @@ fn test_registration_upload() -> Result<(), ProtocolError> {
)?
.finish(
&mut finish_registration_rng,
RegistrationResponse::deserialize(&parameters.registration_response[..]).unwrap(),
RegistrationResponse::deserialize(&parameters.registration_response[..])?,
ClientRegistrationFinishParameters::WithIdentifiers(parameters.id_u, parameters.id_s),
)?;
@@ -500,8 +501,9 @@ fn test_password_file() -> Result<(), ProtocolError> {
let server_registration = ServerRegistration::<RistrettoSha5123dhNoSlowHash>::try_from(
&parameters.server_registration_state[..],
)?;
let password_file = server_registration
.finish(RegistrationUpload::deserialize(&parameters.registration_upload[..]).unwrap())?;
let password_file = server_registration.finish(RegistrationUpload::deserialize(
&parameters.registration_upload[..],
)?)?;
assert_eq!(
hex::encode(parameters.password_file),
@@ -545,12 +547,11 @@ fn test_credential_response() -> Result<(), ProtocolError> {
CycleRng::new([parameters.server_e_sk, parameters.server_nonce].concat());
let server_login_start_result = ServerLogin::<RistrettoSha5123dhNoSlowHash>::start(
&mut server_e_sk_and_nonce_rng,
ServerRegistration::try_from(&parameters.password_file[..]).unwrap(),
&Key::try_from(&parameters.server_s_sk[..]).unwrap(),
ServerRegistration::try_from(&parameters.password_file[..])?,
&Key::try_from(&parameters.server_s_sk[..])?,
CredentialRequest::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.credential_request[..],
)
.unwrap(),
)?,
ServerLoginStartParameters::WithInfoAndIdentifiers(
parameters.einfo2.to_vec(),
parameters.id_u,
@@ -577,8 +578,7 @@ fn test_credential_finalization() -> Result<(), ProtocolError> {
let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap());
let client_login_finish_result =
ClientLogin::<RistrettoSha5123dhNoSlowHash>::try_from(&parameters.client_login_state[..])
.unwrap()
ClientLogin::<RistrettoSha5123dhNoSlowHash>::try_from(&parameters.client_login_state[..])?
.finish(
CredentialResponse::<RistrettoSha5123dhNoSlowHash>::deserialize(
&parameters.credential_response[..],