diff --git a/Cargo.lock b/Cargo.lock index 8c30e27..c4df11c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", -] diff --git a/Cargo.toml b/Cargo.toml index c80ccfc..3b6094d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/examples/digital_locker.rs b/examples/digital_locker.rs index c6768cc..36f7036 100644 --- a/examples/digital_locker.rs +++ b/examples/digital_locker.rs @@ -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")) } diff --git a/src/envelope.rs b/src/envelope.rs index 216b2d5..b0f9c8c 100644 --- a/src/envelope.rs +++ b/src/envelope.rs @@ -100,6 +100,9 @@ pub(crate) struct Envelope { hmac: GenericArray::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 { pub(crate) client_s_sk: Vec, pub(crate) export_key: GenericArray::OutputSize>, diff --git a/src/key_exchange/traits.rs b/src/key_exchange/traits.rs index 089b322..cfe7b00 100644 --- a/src/key_exchange/traits.rs +++ b/src/key_exchange/traits.rs @@ -21,7 +21,6 @@ pub trait KeyExchange { type KE3Message: for<'r> TryFrom<&'r [u8], Error = PakeError> + ToBytes; fn generate_ke1( - l1_component: Vec, info: Vec, rng: &mut R, ) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>; @@ -44,6 +43,7 @@ pub trait KeyExchange { l2_component: Vec, ke2_message: Self::KE2Message, ke1_state: &Self::KE1State, + serialized_credential_request: &[u8], server_s_pk: Key, client_s_sk: Key, id_u: Vec, diff --git a/src/key_exchange/tripledh.rs b/src/key_exchange/tripledh.rs index 71e4ac1..8900a63 100644 --- a/src/key_exchange/tripledh.rs +++ b/src/key_exchange/tripledh.rs @@ -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 KeyExchange for TripleDH { type KE3Message = KE3Message<::OutputSize>; fn generate_ke1( - alpha_bytes: Vec, info: Vec, rng: &mut R, ) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> { let client_e_kp = KeyPair::::generate_random(rng); let client_nonce: GenericArray = { - 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 KeyExchange 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 KeyExchange for TripleDH { ) -> Result<(Vec, Self::KE2State, Self::KE2Message), ProtocolError> { let server_e_kp = KeyPair::::generate_random(rng); let server_nonce: GenericArray = { - 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::( @@ -169,6 +163,7 @@ impl KeyExchange for TripleDH { l2_component: Vec, ke2_message: Self::KE2Message, ke1_state: &Self::KE1State, + serialized_credential_request: &[u8], server_s_pk: Key, client_s_sk: Key, id_u: Vec, @@ -190,7 +185,7 @@ impl KeyExchange for TripleDH { )?; let transcript: Vec = [ - &ke1_state.serialized_credential_request[..], + &serialized_credential_request, &l2_component[..], &ke2_message.to_bytes_without_mac(), ] @@ -258,7 +253,7 @@ impl KeyExchange for TripleDH { } fn ke2_message_size() -> usize { - NONCE_LEN + KEY_LEN + <::OutputSize as Unsigned>::to_usize() + NonceLen::to_usize() + KEY_LEN + <::OutputSize as Unsigned>::to_usize() } } @@ -267,7 +262,6 @@ impl KeyExchange for TripleDH { pub struct KE1State { client_e_sk: Key, client_nonce: GenericArray, - serialized_credential_request: Vec, } /// The first key exchange message @@ -282,26 +276,21 @@ impl TryFrom<&[u8]> for KE1State { type Error = PakeError; fn try_from(bytes: &[u8]) -> Result { - 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 { - let output: Vec = [ - &self.client_e_sk.to_arr(), - &self.client_nonce[..], - &self.serialized_credential_request[..], - ] - .concat(); + let output: Vec = [&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 { + 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> TryFrom<&[u8]> for KE2Message { type Error = PakeError; fn try_from(input: &[u8]) -> Result { - 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> TryFrom<&[u8]> for KE2Message { 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), diff --git a/src/map_to_curve.rs b/src/map_to_curve.rs index 0e301ac..f3c5564 100644 --- a/src/map_to_curve.rs +++ b/src/map_to_curve.rs @@ -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(msg: &[u8], dst: &[u8]) -> Result { - // FIXME use generic_array and turn this into a compile-time error if size mismatch let uniform_bytes = expand_message_xmd::(msg, dst, ::OutputSize::to_usize())?; Ok(::hash_to_curve( diff --git a/src/messages.rs b/src/messages.rs index 531714d..7f947aa 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -259,12 +259,24 @@ pub struct CredentialResponse { impl CredentialResponse { /// Serialization into bytes pub fn serialize(&self) -> Vec { - let mut credential_response: Vec = 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, + ) -> Vec { + [ + &beta.to_arr(), + &serialize(&server_s_pk.to_arr().to_vec(), 2)[..], + &envelope.to_bytes(), + ] + .concat() } /// Deserialization from bytes diff --git a/src/opaque.rs b/src/opaque.rs index 923f0ed..b21e4ea 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -408,6 +408,7 @@ pub struct ClientLogin { /// token containing the client's password and the blinding factor token: oprf::Token, ke1_state: >::KE1State, + serialized_credential_request: Vec, } impl TryFrom<&[u8]> for ClientLogin { @@ -427,7 +428,8 @@ impl TryFrom<&[u8]> for ClientLogin { 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 = >::KE1State::try_from( &ke1_state_bytes[..], @@ -438,6 +440,7 @@ impl TryFrom<&[u8]> for ClientLogin { blind: blinding_factor, }, ke1_state, + serialized_credential_request, }) } } @@ -447,6 +450,7 @@ impl ClientLogin { pub fn to_bytes(&self) -> Vec { let output: Vec = [ &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 ClientLogin { let (token, alpha) = oprf::blind::(&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 ClientLogin { 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 ServerLogin { let l1_bytes = &l1.to_bytes(); let beta = oprf::evaluate(l1.alpha, &password_file.oprf_key); - let server_s_pk = KeyPair::::public_from_private(&server_s_sk); - // TODO: must match serialization of credential response, could be done more cleanly - let l2_component: Vec = [ - &beta.to_arr()[..], - &serialize(&server_s_pk.to_arr()[..], 2), - &envelope.to_bytes()[..], - ] - .concat(); + let credential_response_component = + CredentialResponse::::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 ServerLogin { e_info, )?; - let l2 = CredentialResponse { + let credential_response = CredentialResponse { beta, server_s_pk, envelope, @@ -804,7 +807,7 @@ impl ServerLogin { Ok(ServerLoginStartResult { plain_info, - message: l2, + message: credential_response, state: Self { _cs: PhantomData, ke2_state, diff --git a/src/serialization/mod.rs b/src/serialization/mod.rs index eb51f03..69c20cc 100644 --- a/src/serialization/mod.rs +++ b/src/serialization/mod.rs @@ -22,7 +22,6 @@ pub(crate) fn i2osp(input: usize, length: usize) -> Vec { // Corresponds to the OS2IP() function from RFC8017 pub(crate) fn os2ip(input: &[u8]) -> Result { if input.len() > std::mem::size_of::() { - // TODO:: check RFC compliance in refusing this return Err(PakeError::SerializationError); } diff --git a/src/serialization/tests.rs b/src/serialization/tests.rs index 05b142f..f0aa69f 100644 --- a/src/serialization/tests.rs +++ b/src/serialization/tests.rs @@ -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 = ::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 = [&sc.as_bytes()[..], &serialize(&l1_data, 2), &pw[..]].concat(); + // serialization order: scalar, credential_request, ke1_state, password + let bytes: Vec = [ + &sc.as_bytes()[..], + &serialize(&serialized_credential_request, 2), + &serialize(&l1_data, 2), + &pw[..], + ] + .concat(); let reg = ClientLogin::::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); diff --git a/src/tests/full_test.rs b/src/tests/full_test.rs index b7d9424..533ed97 100644 --- a/src/tests/full_test.rs +++ b/src/tests/full_test.rs @@ -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() -> 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::::start( &mut oprf_key_rng, - RegistrationRequest::deserialize(¶meters.registration_request[..]).unwrap(), - &Key::try_from(¶meters.server_s_pk[..]).unwrap(), + RegistrationRequest::deserialize(¶meters.registration_request[..])?, + &Key::try_from(¶meters.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(¶meters.registration_response[..]).unwrap(), + RegistrationResponse::deserialize(¶meters.registration_response[..])?, ClientRegistrationFinishParameters::WithIdentifiers(parameters.id_u, parameters.id_s), )?; @@ -500,8 +501,9 @@ fn test_password_file() -> Result<(), ProtocolError> { let server_registration = ServerRegistration::::try_from( ¶meters.server_registration_state[..], )?; - let password_file = server_registration - .finish(RegistrationUpload::deserialize(¶meters.registration_upload[..]).unwrap())?; + let password_file = server_registration.finish(RegistrationUpload::deserialize( + ¶meters.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::::start( &mut server_e_sk_and_nonce_rng, - ServerRegistration::try_from(¶meters.password_file[..]).unwrap(), - &Key::try_from(¶meters.server_s_sk[..]).unwrap(), + ServerRegistration::try_from(¶meters.password_file[..])?, + &Key::try_from(¶meters.server_s_sk[..])?, CredentialRequest::::deserialize( ¶meters.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::::try_from(¶meters.client_login_state[..]) - .unwrap() + ClientLogin::::try_from(¶meters.client_login_state[..])? .finish( CredentialResponse::::deserialize( ¶meters.credential_response[..],