diff --git a/benches/oprf.rs b/benches/oprf.rs index ab8c776..899626e 100644 --- a/benches/oprf.rs +++ b/benches/oprf.rs @@ -11,7 +11,7 @@ use curve25519_dalek::{edwards::EdwardsPoint, ristretto::RistrettoPoint}; use generic_array::arr; use opaque_ke::{ group::Group, - oprf::{generate_oprf1_shim, generate_oprf2_shim, generate_oprf3_shim, OprfClientBytes}, + oprf::{blind_shim, evaluate_shim, unblind_and_finalize_shim}, }; use rand::{prelude::ThreadRng, thread_rng}; use sha2::Sha256; @@ -20,12 +20,9 @@ fn oprf1(c: &mut Criterion) { let mut csprng: ThreadRng = thread_rng(); let input = b"hunter2"; - c.bench_function("generate_oprf1 with Ristretto", move |b| { + c.bench_function("blind with Ristretto", move |b| { b.iter(|| { - let OprfClientBytes { - alpha: _alpha, - blinding_factor: _blinding_factor, - } = generate_oprf1_shim::<_, RistrettoPoint>(&input[..], None, &mut csprng).unwrap(); + blind_shim::<_, RistrettoPoint>(&input[..], &mut csprng).unwrap(); }) }); } @@ -34,12 +31,9 @@ fn oprf1_edwards(c: &mut Criterion) { let mut csprng: ThreadRng = thread_rng(); let input = b"hunter2"; - c.bench_function("generate_oprf1 with Edwards", move |b| { + c.bench_function("blind with Edwards", move |b| { b.iter(|| { - let OprfClientBytes { - alpha: _alpha, - blinding_factor: _blinding_factor, - } = generate_oprf1_shim::<_, EdwardsPoint>(&input[..], None, &mut csprng).unwrap(); + blind_shim::<_, EdwardsPoint>(&input[..], &mut csprng).unwrap(); }) }); } @@ -48,19 +42,16 @@ fn oprf2(c: &mut Criterion) { let mut csprng: ThreadRng = thread_rng(); let input = b"hunter2"; - let OprfClientBytes { - alpha, - blinding_factor: _blinding_factor, - } = generate_oprf1_shim::<_, RistrettoPoint>(&input[..], None, &mut csprng).unwrap(); + let (_, alpha) = blind_shim::<_, RistrettoPoint>(&input[..], &mut csprng).unwrap(); let salt_bytes = arr![ u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]; let salt = RistrettoPoint::from_scalar_slice(&salt_bytes).unwrap(); - c.bench_function("generate_oprf2 with Ristretto", move |b| { + c.bench_function("evaluate with Ristretto", move |b| { b.iter(|| { - let _beta = generate_oprf2_shim::(alpha, &salt).unwrap(); + let _beta = evaluate_shim::(alpha, &salt).unwrap(); }) }); } @@ -69,19 +60,16 @@ fn oprf2_edwards(c: &mut Criterion) { let mut csprng: ThreadRng = thread_rng(); let input = b"hunter2"; - let OprfClientBytes { - alpha, - blinding_factor: _blinding_factor, - } = generate_oprf1_shim::<_, EdwardsPoint>(&input[..], None, &mut csprng).unwrap(); + let (_, alpha) = blind_shim::<_, EdwardsPoint>(&input[..], &mut csprng).unwrap(); let salt_bytes = arr![ u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]; let salt = RistrettoPoint::from_scalar_slice(&salt_bytes).unwrap(); - c.bench_function("generate_oprf2 with Edwards", move |b| { + c.bench_function("evaluate with Edwards", move |b| { b.iter(|| { - let _beta = generate_oprf2_shim::(alpha, &salt).unwrap(); + let _beta = evaluate_shim::(alpha, &salt).unwrap(); }) }); } @@ -90,21 +78,17 @@ fn oprf3(c: &mut Criterion) { let mut csprng: ThreadRng = thread_rng(); let input = b"hunter2"; - let OprfClientBytes { - alpha, - blinding_factor, - } = generate_oprf1_shim::<_, RistrettoPoint>(&input[..], None, &mut csprng).unwrap(); + let (token, alpha) = blind_shim::<_, RistrettoPoint>(&input[..], &mut csprng).unwrap(); let salt_bytes = arr![ u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]; let salt = RistrettoPoint::from_scalar_slice(&salt_bytes).unwrap(); - let beta = generate_oprf2_shim::(alpha, &salt).unwrap(); + let beta = evaluate_shim::(alpha, &salt).unwrap(); - c.bench_function("generate_oprf3 with Ristretto", move |b| { + c.bench_function("unblind_and_finalize with Ristretto", move |b| { b.iter(|| { - let _res = generate_oprf3_shim::(input, beta, &blinding_factor) - .unwrap(); + let _res = unblind_and_finalize_shim::(&token, beta).unwrap(); }) }); } @@ -113,21 +97,17 @@ fn oprf3_edwards(c: &mut Criterion) { let mut csprng: ThreadRng = thread_rng(); let input = b"hunter2"; - let OprfClientBytes { - alpha, - blinding_factor, - } = generate_oprf1_shim::<_, EdwardsPoint>(&input[..], None, &mut csprng).unwrap(); + let (token, alpha) = blind_shim::<_, EdwardsPoint>(&input[..], &mut csprng).unwrap(); let salt_bytes = arr![ u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]; let salt = RistrettoPoint::from_scalar_slice(&salt_bytes).unwrap(); - let beta = generate_oprf2_shim::(alpha, &salt).unwrap(); + let beta = evaluate_shim::(alpha, &salt).unwrap(); - c.bench_function("generate_oprf3 with Edwards", move |b| { + c.bench_function("unblind_and_finalize with Edwards", move |b| { b.iter(|| { - let _res = - generate_oprf3_shim::(input, beta, &blinding_factor).unwrap(); + let _res = unblind_and_finalize_shim::(&token, beta).unwrap(); }) }); } diff --git a/src/lib.rs b/src/lib.rs index d8e2bb5..87cdba5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -89,7 +89,6 @@ //! let mut client_rng = OsRng; //! let (r1, client_state) = ClientRegistration::::start( //! b"password", -//! Some(b"pepper"), //! &mut client_rng, //! )?; //! # Ok::<(), ProtocolError>(()) @@ -119,7 +118,6 @@ //! # let mut client_rng = OsRng; //! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! use opaque_ke::opaque::ServerRegistration; @@ -153,7 +151,6 @@ //! # let mut client_rng = OsRng; //! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; @@ -188,7 +185,6 @@ //! # let mut client_rng = OsRng; //! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; @@ -232,7 +228,6 @@ //! let mut client_rng = OsRng; //! let (l1, client_state) = ClientLogin::::start( //! b"password", -//! Some(b"pepper"), //! &mut client_rng, //! )?; //! # Ok::<(), ProtocolError>(()) @@ -262,7 +257,6 @@ //! # let mut client_rng = OsRng; //! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; @@ -272,7 +266,6 @@ //! # let password_file_bytes = server_state.finish(r3)?.to_bytes(); //! # let (l1, client_state) = ClientLogin::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! use opaque_ke::opaque::ServerLogin; @@ -308,7 +301,6 @@ //! # let mut client_rng = OsRng; //! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; @@ -318,7 +310,6 @@ //! # let password_file_bytes = server_state.finish(r3)?.to_bytes(); //! # let (l1, client_state) = ClientLogin::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # use std::convert::TryFrom; @@ -365,7 +356,6 @@ //! # let mut client_rng = OsRng; //! # let (r1, client_state) = ClientRegistration::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # let mut server_rng = OsRng; @@ -375,7 +365,6 @@ //! # let password_file_bytes = server_state.finish(r3)?.to_bytes(); //! # let (l1, client_state) = ClientLogin::::start( //! # b"password", -//! # Some(b"pepper"), //! # &mut client_rng, //! # )?; //! # use std::convert::TryFrom; diff --git a/src/map_to_curve.rs b/src/map_to_curve.rs index a7667db..64ffabe 100644 --- a/src/map_to_curve.rs +++ b/src/map_to_curve.rs @@ -15,19 +15,22 @@ use sha2::{Sha256, Sha512}; /// A subtrait of Group specifying how to hash a password into a point pub trait GroupWithMapToCurve: Group { /// transforms a password and optional pepper into a curve point - fn map_to_curve(password: &[u8], pepper: Option<&[u8]>) -> Self; + fn map_to_curve(password: &[u8], dst: Option<&[u8]>) -> Self; } +// TODO: incorporate expand_message_xmd from https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-10.txt +// instead of using HKDF-extract here + impl GroupWithMapToCurve for RistrettoPoint { - fn map_to_curve(password: &[u8], pepper: Option<&[u8]>) -> Self { - let (hashed_input, _) = Hkdf::::extract(pepper, password); + fn map_to_curve(password: &[u8], dst: Option<&[u8]>) -> Self { + let (hashed_input, _) = Hkdf::::extract(dst, password); ::hash_to_curve(&hashed_input) } } impl GroupWithMapToCurve for EdwardsPoint { - fn map_to_curve(password: &[u8], pepper: Option<&[u8]>) -> Self { - let (hashed_input, _) = Hkdf::::extract(pepper, password); + fn map_to_curve(password: &[u8], dst: Option<&[u8]>) -> Self { + let (hashed_input, _) = Hkdf::::extract(dst, password); ::hash_to_curve(&hashed_input) } } diff --git a/src/opaque.rs b/src/opaque.rs index 160cefd..d016d1f 100644 --- a/src/opaque.rs +++ b/src/opaque.rs @@ -17,7 +17,6 @@ use crate::{ key_exchange::traits::{KeyExchange, ToBytes}, keypair::{KeyPair, SizedBytes}, oprf, - oprf::OprfClientBytes, serialization::{ serialize, tokenize, u8_to_credential_type, CredentialType, ProtocolMessageType, }, @@ -492,10 +491,8 @@ pub struct ClientRegistration { id_u: Vec, /// Server identity id_s: Vec, - /// a blinding factor - pub(crate) blinding_factor: ::Scalar, - /// the client's password - password: Vec, + /// token containing the client's password and the blinding factor + pub(crate) token: oprf::Token, } impl TryFrom<&[u8]> for ClientRegistration { @@ -524,8 +521,10 @@ impl TryFrom<&[u8]> for ClientRegistration { Ok(Self { id_u, id_s, - blinding_factor, - password, + token: oprf::Token { + data: password, + blind: blinding_factor, + }, }) } } @@ -536,8 +535,8 @@ impl ClientRegistration { let output: Vec = [ &serialize(&self.id_u, 2), &serialize(&self.id_s, 2), - &CS::Group::scalar_as_bytes(&self.blinding_factor)[..], - &self.password, + &CS::Group::scalar_as_bytes(&self.token.blind)[..], + &self.token.data, ] .concat(); output @@ -566,19 +565,17 @@ impl ClientRegistration { /// type SlowHash = opaque_ke::slow_hash::NoOpHash; /// } /// let mut rng = OsRng; - /// let (register_m1, registration_state) = ClientRegistration::::start(b"hunter2", None, &mut rng)?; + /// let (register_m1, registration_state) = ClientRegistration::::start(b"hunter2", &mut rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( password: &[u8], - pepper: Option<&[u8]>, blinding_factor_rng: &mut R, ) -> Result<(RegisterFirstMessage, Self), ProtocolError> { Self::start_with_user_and_server_name( &Vec::new(), &Vec::new(), password, - pepper, blinding_factor_rng, ) } @@ -588,13 +585,31 @@ impl ClientRegistration { user_name: &[u8], server_name: &[u8], password: &[u8], - pepper: Option<&[u8]>, blinding_factor_rng: &mut R, ) -> Result<(RegisterFirstMessage, Self), ProtocolError> { - let OprfClientBytes { - alpha, - blinding_factor, - } = oprf::generate_oprf1::(&password, pepper, blinding_factor_rng)?; + Self::start_with_user_and_server_name_and_postprocessing( + user_name, + server_name, + password, + blinding_factor_rng, + std::convert::identity, + ) + } + + /// Same as ClientRegistration::start, but also accepts a username and server name as input as well as + /// an optional postprocessing function for the blinding factor + pub fn start_with_user_and_server_name_and_postprocessing( + user_name: &[u8], + server_name: &[u8], + password: &[u8], + blinding_factor_rng: &mut R, + postprocess: fn(::Scalar) -> ::Scalar, + ) -> Result<(RegisterFirstMessage, Self), ProtocolError> { + let (token, alpha) = oprf::blind_with_postprocessing::( + &password, + blinding_factor_rng, + postprocess, + )?; Ok(( RegisterFirstMessage:: { @@ -604,8 +619,7 @@ impl ClientRegistration { Self { id_u: user_name.to_vec(), id_s: server_name.to_vec(), - blinding_factor, - password: password.to_vec(), + token, }, )) } @@ -642,7 +656,7 @@ impl ClientRegistration { /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", &mut client_rng)?; /// let (register_m2, server_state) = /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// let mut client_rng = OsRng; @@ -668,11 +682,8 @@ impl ClientRegistration { ) -> Result, ProtocolError> { let client_static_keypair = CS::KeyFormat::generate_random(rng)?; - let password_derived_key = get_password_derived_key::( - self.password.clone(), - r2.beta, - &self.blinding_factor, - )?; + let password_derived_key = + get_password_derived_key::(&self.token, r2.beta)?; let mut credentials_map: HashMap> = HashMap::new(); credentials_map.insert( @@ -703,8 +714,8 @@ impl ClientRegistration { // This can't be derived because of the use of a phantom parameter impl Zeroize for ClientRegistration { fn zeroize(&mut self) { - self.password.zeroize(); - self.blinding_factor.zeroize(); + self.token.data.zeroize(); + self.token.blind.zeroize(); } } @@ -717,8 +728,8 @@ impl Drop for ClientRegistration { // This can't be derived because of the use of a phantom parameter impl Zeroize for ClientLogin { fn zeroize(&mut self) { - self.password.zeroize(); - self.blinding_factor.zeroize(); + self.token.data.zeroize(); + self.token.blind.zeroize(); } } @@ -825,7 +836,7 @@ where /// } /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; - /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", &mut client_rng)?; /// let (register_m2, server_state) = /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// # Ok::<(), ProtocolError>(()) @@ -862,7 +873,7 @@ where let oprf_key = CS::Group::random_scalar(rng); // Compute beta = alpha^oprf_key - let beta = oprf::generate_oprf2::(message.alpha, &oprf_key)?; + let beta = oprf::evaluate::(message.alpha, &oprf_key)?; Ok(( RegisterSecondMessage { @@ -902,7 +913,7 @@ where /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", &mut client_rng)?; /// let (register_m2, server_state) = /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// let mut client_rng = OsRng; @@ -931,11 +942,8 @@ pub struct ClientLogin { id_u: Vec, /// Server identity id_s: Vec, - /// A blinding factor, which is used to mask (and unmask) secret - /// information before transmission - blinding_factor: ::Scalar, - /// The user's password - password: Vec, + /// token containing the client's password and the blinding factor + token: oprf::Token, ke1_state: >::KE1State, } @@ -970,8 +978,10 @@ impl TryFrom<&[u8]> for ClientLogin { Ok(Self { id_u, id_s, - blinding_factor, - password, + token: oprf::Token { + data: password, + blind: blinding_factor, + }, ke1_state, }) } @@ -983,9 +993,9 @@ impl ClientLogin { let output: Vec = [ &serialize(&self.id_u, 2), &serialize(&self.id_s, 2), - &CS::Group::scalar_as_bytes(&self.blinding_factor)[..], + &CS::Group::scalar_as_bytes(&self.token.blind)[..], &self.ke1_state.to_bytes(), - &self.password, + &self.token.data, ] .concat(); output @@ -1020,15 +1030,14 @@ impl ClientLogin { /// type SlowHash = opaque_ke::slow_hash::NoOpHash; /// } /// let mut client_rng = OsRng; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", &mut client_rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` pub fn start( password: &[u8], - pepper: Option<&[u8]>, rng: &mut R, ) -> Result<(LoginFirstMessage, Self), ProtocolError> { - Self::start_with_user_and_server_name(&Vec::new(), &Vec::new(), password, pepper, rng) + Self::start_with_user_and_server_name(&Vec::new(), &Vec::new(), password, rng) } /// Same as start, but allows the user to supply a username and server name @@ -1036,13 +1045,27 @@ impl ClientLogin { user_name: &[u8], server_name: &[u8], password: &[u8], - pepper: Option<&[u8]>, rng: &mut R, ) -> Result<(LoginFirstMessage, Self), ProtocolError> { - let OprfClientBytes { - alpha, - blinding_factor, - } = oprf::generate_oprf1::(&password, pepper, rng)?; + Self::start_with_user_and_server_name_and_postprocessing( + user_name, + server_name, + password, + rng, + std::convert::identity, + ) + } + + /// Same as start, but allows the user to supply a username and server name and postprocessing function + pub fn start_with_user_and_server_name_and_postprocessing( + user_name: &[u8], + server_name: &[u8], + password: &[u8], + rng: &mut R, + postprocess: fn(::Scalar) -> ::Scalar, + ) -> Result<(LoginFirstMessage, Self), ProtocolError> { + let (token, alpha) = + oprf::blind_with_postprocessing::(&password, rng, postprocess)?; let (ke1_state, ke1_message) = CS::KeyExchange::generate_ke1(alpha.to_arr().to_vec(), rng)?; @@ -1057,8 +1080,7 @@ impl ClientLogin { Self { id_u: user_name.to_vec(), id_s: server_name.to_vec(), - blinding_factor, - password: password.to_vec(), + token, ke1_state, }, )) @@ -1089,12 +1111,12 @@ impl ClientLogin { /// } /// let mut client_rng = OsRng; /// # let mut server_rng = OsRng; - /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", &mut client_rng)?; /// # let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; /// # let (register_m2, server_state) = ServerRegistration::::start(register_m1, &mut server_rng)?; /// # let (register_m3, _export_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// # let p_file = server_state.finish(register_m3)?; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", &mut client_rng)?; /// let (login_m2, server_login_state) = ServerLogin::start(p_file, &server_kp.private(), login_m1, &mut server_rng)?; /// let (login_m3, client_transport, _export_key) = client_login_state.finish(login_m2, &server_kp.public(), &mut client_rng)?; /// # Ok::<(), ProtocolError>(()) @@ -1107,11 +1129,8 @@ impl ClientLogin { ) -> Result, ProtocolError> { let l2_bytes: Vec = [&l2.beta.to_arr()[..], &l2.envelope.to_bytes()].concat(); - let password_derived_key = get_password_derived_key::( - self.password.clone(), - l2.beta, - &self.blinding_factor, - )?; + let password_derived_key = + get_password_derived_key::(&self.token, l2.beta)?; let opened_envelope = &l2 .envelope @@ -1194,12 +1213,12 @@ impl ServerLogin { /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", &mut client_rng)?; /// # let (register_m2, server_state) = /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// # let (register_m3, _export_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// # let p_file = server_state.finish(register_m3)?; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", &mut client_rng)?; /// let (login_m2, server_login_state) = ServerLogin::start(p_file, &server_kp.private(), login_m1, &mut server_rng)?; /// # Ok::<(), ProtocolError>(()) /// ``` @@ -1210,7 +1229,7 @@ impl ServerLogin { rng: &mut R, ) -> Result, ProtocolError> { let l1_bytes = &l1.to_bytes(); - let beta = oprf::generate_oprf2(l1.alpha, &password_file.oprf_key)?; + let beta = oprf::evaluate(l1.alpha, &password_file.oprf_key)?; let client_s_pk = password_file .client_s_pk @@ -1269,12 +1288,12 @@ impl ServerLogin { /// let mut client_rng = OsRng; /// let mut server_rng = OsRng; /// let server_kp = X25519KeyPair::generate_random(&mut server_rng)?; - /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", None, &mut client_rng)?; + /// # let (register_m1, client_state) = ClientRegistration::::start(b"hunter2", &mut client_rng)?; /// # let (register_m2, server_state) = /// ServerRegistration::::start(register_m1, &mut server_rng)?; /// # let (register_m3, _export_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; /// # let p_file = server_state.finish(register_m3)?; - /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", None, &mut client_rng)?; + /// let (login_m1, client_login_state) = ClientLogin::::start(b"hunter2", &mut client_rng)?; /// let (login_m2, server_login_state) = ServerLogin::start(p_file, &server_kp.private(), login_m1, &mut server_rng)?; /// let (login_m3, client_transport, _export_key) = client_login_state.finish(login_m2, &server_kp.public(), &mut client_rng)?; /// let mut server_transport = server_login_state.finish(login_m3)?; @@ -1296,10 +1315,9 @@ impl ServerLogin { // Helper functions fn get_password_derived_key, D: Hash>( - password: Vec, + token: &oprf::Token, beta: G, - blinding_factor: &G::Scalar, ) -> Result, InternalPakeError> { - let oprf_output = oprf::generate_oprf3::(&password, beta, blinding_factor)?; + let oprf_output = oprf::unblind_and_finalize::(token, beta)?; SH::hash(oprf_output) } diff --git a/src/oprf.rs b/src/oprf.rs index c00480c..d189307 100644 --- a/src/oprf.rs +++ b/src/oprf.rs @@ -11,47 +11,51 @@ use generic_array::GenericArray; use hkdf::Hkdf; use rand_core::{CryptoRng, RngCore}; -pub struct OprfClientBytes { - pub alpha: Grp, - pub blinding_factor: Grp::Scalar, +/// Used to store the OPRF input and blinding factor +pub struct Token { + pub(crate) data: Vec, + pub(crate) blind: Grp::Scalar, } +static STR_VOPRF: &[u8] = b"VOPRF05"; + /// Computes the first step for the multiplicative blinding version of DH-OPRF. This /// message is sent from the client (who holds the input) to the server (who holds the OPRF key). /// The client can also pass in an optional "pepper" string to be mixed in with the input through /// an HKDF computation. -pub(crate) fn generate_oprf1( +pub(crate) fn blind_with_postprocessing( input: &[u8], - pepper: Option<&[u8]>, blinding_factor_rng: &mut R, -) -> Result, InternalPakeError> { - let mapped_point = G::map_to_curve(input, pepper); + postprocess: fn(G::Scalar) -> G::Scalar, +) -> Result<(Token, G), InternalPakeError> { + let mapped_point = G::map_to_curve(input, Some(STR_VOPRF)); // TODO: add contextString from RFC let blinding_factor = G::random_scalar(blinding_factor_rng); - let alpha = mapped_point * &blinding_factor; - Ok(OprfClientBytes { - alpha, - blinding_factor, - }) + let blind = postprocess(blinding_factor); + let blind_token = mapped_point * &blind; + Ok(( + Token { + data: input.to_vec(), + blind, + }, + blind_token, + )) } /// Computes the second step for the multiplicative blinding version of DH-OPRF. This /// message is sent from the server (who holds the OPRF key) to the client. -pub(crate) fn generate_oprf2( - point: G, - oprf_key: &G::Scalar, -) -> Result { +pub(crate) fn evaluate(point: G, oprf_key: &G::Scalar) -> Result { Ok(point * oprf_key) } /// Computes the third step for the multiplicative blinding version of DH-OPRF, in which /// the client unblinds the server's message. -pub(crate) fn generate_oprf3( - input: &[u8], +pub(crate) fn unblind_and_finalize( + token: &Token, point: G, - blinding_factor: &G::Scalar, ) -> Result::OutputSize>, InternalPakeError> { - let unblinded = point * &G::scalar_invert(&blinding_factor); - let ikm: Vec = [&unblinded.to_arr()[..], input].concat(); + let unblinded = point * &G::scalar_invert(&token.blind); + let ikm: Vec = [&unblinded.to_arr()[..], &token.data].concat(); + // TODO: implement proper finalizing code here let (prk, _) = Hkdf::::extract(None, &ikm); Ok(prk) } @@ -59,31 +63,26 @@ pub(crate) fn generate_oprf3( // Benchmarking shims #[cfg(feature = "bench")] #[inline] -pub fn generate_oprf1_shim( +pub fn blind_shim( input: &[u8], - pepper: Option<&[u8]>, blinding_factor_rng: &mut R, -) -> Result, InternalPakeError> { - generate_oprf1(input, pepper, blinding_factor_rng) +) -> Result<(Token, G), InternalPakeError> { + blind_with_postprocessing(input, blinding_factor_rng, std::convert::identity) } #[cfg(feature = "bench")] #[inline] -pub fn generate_oprf2_shim( - point: G, - oprf_key: &G::Scalar, -) -> Result { - generate_oprf2(point, oprf_key) +pub fn evaluate_shim(point: G, oprf_key: &G::Scalar) -> Result { + evaluate(point, oprf_key) } #[cfg(feature = "bench")] #[inline] -pub fn generate_oprf3_shim( - input: &[u8], +pub fn unblind_and_finalize_shim( + token: &Token, point: G, - blinding_factor: &G::Scalar, ) -> Result::OutputSize>, InternalPakeError> { - generate_oprf3::(input, point, blinding_factor) + unblind_and_finalize::(token, point) } // Tests @@ -103,7 +102,7 @@ mod tests { input: &[u8], oprf_key: &[u8; 32], ) -> GenericArray::ElemLen> { - let (hashed_input, _) = Hkdf::::extract(None, &input); + let (hashed_input, _) = Hkdf::::extract(Some(STR_VOPRF), &input); let point = RistrettoPoint::hash_to_curve(GenericArray::from_slice(&hashed_input)); let scalar = RistrettoPoint::from_scalar_slice(GenericArray::from_slice(&oprf_key[..])).unwrap(); @@ -118,18 +117,19 @@ mod tests { fn oprf_retrieval() -> Result<(), InternalPakeError> { let input = b"hunter2"; let mut rng = OsRng; - let OprfClientBytes { - alpha, - blinding_factor, - } = generate_oprf1::<_, RistrettoPoint>(&input[..], None, &mut rng)?; - let salt_bytes = arr![ + let (token, alpha) = blind_with_postprocessing::<_, RistrettoPoint>( + &input[..], + &mut rng, + std::convert::identity, + )?; + let oprf_key_bytes = arr![ u8; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]; - let salt = RistrettoPoint::from_scalar_slice(&salt_bytes)?; - let beta = generate_oprf2::(alpha, &salt)?; - let res = generate_oprf3::(input, beta, &blinding_factor)?; - let res2 = prf(&input[..], &salt.as_bytes()); + let oprf_key = RistrettoPoint::from_scalar_slice(&oprf_key_bytes)?; + let beta = evaluate::(alpha, &oprf_key)?; + let res = unblind_and_finalize::(&token, beta)?; + let res2 = prf(&input[..], &oprf_key.as_bytes()); assert_eq!(res, res2); Ok(()) } @@ -139,14 +139,15 @@ mod tests { let mut rng = OsRng; let mut input = vec![0u8; 64]; rng.fill_bytes(&mut input); - let OprfClientBytes { - alpha, - blinding_factor, - } = generate_oprf1::<_, RistrettoPoint>(&input, None, &mut rng).unwrap(); - let res = generate_oprf3::(&input, alpha, &blinding_factor) - .unwrap(); + let (token, alpha) = blind_with_postprocessing::<_, RistrettoPoint>( + &input, + &mut rng, + std::convert::identity, + ) + .unwrap(); + let res = unblind_and_finalize::(&token, alpha).unwrap(); - let (hashed_input, _) = Hkdf::::extract(None, &input); + let (hashed_input, _) = Hkdf::::extract(Some(STR_VOPRF), &input); let mut bits = [0u8; 64]; bits.copy_from_slice(&hashed_input); diff --git a/src/tests/opaque_ke_test.rs b/src/tests/opaque_ke_test.rs index 3275275..848afb0 100644 --- a/src/tests/opaque_ke_test.rs +++ b/src/tests/opaque_ke_test.rs @@ -14,6 +14,7 @@ use crate::{ tests::mock_rng::CycleRng, }; use curve25519_dalek::edwards::EdwardsPoint; +use generic_array::GenericArray; use rand_core::{OsRng, RngCore}; use serde_json::Value; use std::convert::TryFrom; @@ -39,10 +40,10 @@ pub struct TestVectorParameters { pub server_s_sk: Vec, pub server_e_pk: Vec, pub server_e_sk: Vec, + pub id_u: Vec, + pub id_s: Vec, pub password: Vec, - pub blinding_factor_raw: Vec, pub blinding_factor: Vec, - pub pepper: Vec, pub oprf_key: Vec, pub envelope_nonce: Vec, pub client_nonce: Vec, @@ -64,35 +65,35 @@ pub struct TestVectorParameters { static TEST_VECTOR: &str = r#" { - "client_s_pk": "8ede26558ada44c55f44a39b3e4811bb71533b52c8331799349f5bf579b0063b", - "client_s_sk": "e0937ce386f57ba61303f56851c6c1c338535ef30a046090c211fbae2b925575", - "client_e_pk": "b2c126715667420809d14b6056d9492051dc31c77cbb39cd61e9d76736118e46", - "client_e_sk": "481a41606adc0d8aa358cee44e36e5cb02f80d445e42551a90f15e1be59bf450", - "server_s_pk": "da106c3619e8c17c2356f4827b33f6f869ab6f99badc8002324925458fecbd0d", - "server_s_sk": "50cc8c336756b9c91badaa42df728c0a06033eca4770a7912f9f2924742f4356", - "server_e_pk": "1848442db55ef8301a28b078317be3c40590fc40b3a356f704ced8c552f59349", - "server_e_sk": "b8d7358f35d79cfa5e288e8ca8356bc806d4463710144767caf65eb9b4f77973", + "client_s_pk": "7489b55c78b380db87d664178e5a020eb2f9bbeac0a44f6fb034ccba8de4a934", + "client_s_sk": "f0499a6c8bac723debd497b672c2d89ed2d96fd190fce247e0dd3019dce8ec59", + "client_e_pk": "c87afc8a9dc82c93dc6fa9d27654c6b909de929e542e94a87ffb7b3256190a46", + "client_e_sk": "107078f8e2ddd88c3d37e611ae932d798403e475f52a6695639999f963063576", + "server_s_pk": "764f186883a88353586c2427bfbe0ff3e5a0f56af414b0c42a5a300fc426ba4d", + "server_s_sk": "c089cb11e78ea8923cc25857ba51fd5da820079a9a2b377bc87dcd496b563e5c", + "server_e_pk": "05d99649994c006a508b996d11a94f52ae68cca44087bdd69602dfceb92d950c", + "server_e_sk": "70c4df069c1a7b70c16cf6409157674c3f8adfd0919f9dd67a254cf167c7e87f", + "id_u": "696455", + "id_s": "696453", "password": "70617373776f7264", - "blinding_factor_raw": "6e5823f7d820cf6996a2cac80e239f58a9d7e8fcbf9588c07dde69dff3c330785bb85a9b1269f079bbcf4b1f428fbc3a977c324120867b9e918c97dad44576f2", - "blinding_factor": "033a794ce47e3fb19206b8e1f2d74e54c874efcf5b5055d2a31d2164efd41a07", - "pepper": "706570706572", - "oprf_key": "fd76f0e1cfa9f971bc5dada4caa87dcba1d69d7ace0064d56107ca1932d36300", - "envelope_nonce": "b25a32f7d33a1225675a8ea65dd4ca0b1a09845ce1f917f66ccc62a695c79f20", - "client_nonce": "e29650629c1463124cb2283068557ba10d35637876b131040b4f8702276e1900", - "server_nonce": "b32c16a32fe0cbb926a4926ff29bcfae2a96fe6e92b45f5ca27de3b6e413d413", - "r1": "01000024000000200e0a8b356d7c81a331dddd6987a888943892863b23e14202895eb27b69da691e", - "r2": "020000280020d63f9afe21e3246534cbfbd230b4497255e0a7bb68c3ad6e2dd9b3f4283c8382000001010103", - "r3": "030000aeb25a32f7d33a1225675a8ea65dd4ca0b1a09845ce1f917f66ccc62a695c79f200023b73a7e011120604ac7d44a5ae7f65102ee79a4f6cc4b544d64b5dc064318cfb35230a70023030020da106c3619e8c17c2356f4827b33f6f869ab6f99badc8002324925458fecbd0d002016ba53f6b3b80db59717025c3a9246d5256bef434ce5f7d2c53b961cb5afe44000208ede26558ada44c55f44a39b3e4811bb71533b52c8331799349f5bf579b0063b", - "l1": "04000024000000200e0a8b356d7c81a331dddd6987a888943892863b23e14202895eb27b69da691ee29650629c1463124cb2283068557ba10d35637876b131040b4f8702276e1900b2c126715667420809d14b6056d9492051dc31c77cbb39cd61e9d76736118e46", - "l2": "050000ae0020d63f9afe21e3246534cbfbd230b4497255e0a7bb68c3ad6e2dd9b3f4283c8382b25a32f7d33a1225675a8ea65dd4ca0b1a09845ce1f917f66ccc62a695c79f200023b73a7e011120604ac7d44a5ae7f65102ee79a4f6cc4b544d64b5dc064318cfb35230a70023030020da106c3619e8c17c2356f4827b33f6f869ab6f99badc8002324925458fecbd0d002016ba53f6b3b80db59717025c3a9246d5256bef434ce5f7d2c53b961cb5afe440b8d7358f35d79cfa5e288e8ca8356bc806d4463710144767caf65eb9b4f779731848442db55ef8301a28b078317be3c40590fc40b3a356f704ced8c552f59349732f8a81df2e21f59afd20155576e6191439e4fc4212b78a74a1198cfca92184", - "l3": "512fa64c0540a5fa5d8ee82910fc91bfff98d6272b9070e37e79832e55916ce5", - "client_registration_state": "00000000033a794ce47e3fb19206b8e1f2d74e54c874efcf5b5055d2a31d2164efd41a0770617373776f7264", - "client_login_state": "00000000033a794ce47e3fb19206b8e1f2d74e54c874efcf5b5055d2a31d2164efd41a07481a41606adc0d8aa358cee44e36e5cb02f80d445e42551a90f15e1be59bf450e29650629c1463124cb2283068557ba10d35637876b131040b4f8702276e190062259ed12ff91ba92d2cb43c7433e73e79c4d6d1536ae77cc9ca808bdffc190b70617373776f7264", - "server_registration_state": "fd76f0e1cfa9f971bc5dada4caa87dcba1d69d7ace0064d56107ca1932d36300", - "server_login_state": "7a78a3ce25b39e78d65c9e648f13f6dbe08b3f91b0ef16565b780d42ca61c6d51a66199867f777c671a8e5fa6e8faf1e1047a26f64adea97b16b7a831204d4bdbc293cebd5bc7f82054b142b10617ee8f2e30f2e39fbcacb3566167fc2021589", - "password_file": "fd76f0e1cfa9f971bc5dada4caa87dcba1d69d7ace0064d56107ca1932d363008ede26558ada44c55f44a39b3e4811bb71533b52c8331799349f5bf579b0063bb25a32f7d33a1225675a8ea65dd4ca0b1a09845ce1f917f66ccc62a695c79f200023b73a7e011120604ac7d44a5ae7f65102ee79a4f6cc4b544d64b5dc064318cfb35230a70023030020da106c3619e8c17c2356f4827b33f6f869ab6f99badc8002324925458fecbd0d002016ba53f6b3b80db59717025c3a9246d5256bef434ce5f7d2c53b961cb5afe440", - "export_key": "57da80dc58057781bf65a4f4b1ea0d77d7eb69fbb2786e26dfdfa0c440ea3611", - "shared_secret": "bc293cebd5bc7f82054b142b10617ee8f2e30f2e39fbcacb3566167fc2021589" + "blinding_factor": "c5629094a160136e99012cf9c8eb19d9d62f87cadf846636bd175064a78b2d00", + "oprf_key": "f431dcb851f3c8202b9dd1a06d8d32434bbab88de4fdd079452faf2359a8d408", + "envelope_nonce": "be38985f7e04dab53e0bddf32cc9eeb64d7f072e089650b681ba4bb04bcfaeb2", + "client_nonce": "0c51879d4ae4cbd047fbf1ba9c7512c25c8d809486f5e6018dff8c525d9f41f1", + "server_nonce": "c896afa11787f8374bbeb3876151bcf4b75c9511a70be3dddce7606a353f3bc3", + "r1": "01000027000369645500201d540787a850896d3c7407e5a2c17729772170dae61640872aeca109d64d4581", + "r2": "02000028002033f9c4bdfe3d2597cbf0c86db2b0b3e81a4400ad4c9618372f6e24d89229d9a4000001010103", + "r3": "030000aebe38985f7e04dab53e0bddf32cc9eeb64d7f072e089650b681ba4bb04bcfaeb20023441a15c5ccbbf863e0db5e03c6edc63696b05d83a66e4aa3e10aa1320936fe8357bc250023030020764f186883a88353586c2427bfbe0ff3e5a0f56af414b0c42a5a300fc426ba4d00208229fa7e73d11f6935de9d5aae17ab5ec77d6cff8d8456437a8098bb54aa9b9300207489b55c78b380db87d664178e5a020eb2f9bbeac0a44f6fb034ccba8de4a934", + "l1": "04000027000369645500201d540787a850896d3c7407e5a2c17729772170dae61640872aeca109d64d45810c51879d4ae4cbd047fbf1ba9c7512c25c8d809486f5e6018dff8c525d9f41f1c87afc8a9dc82c93dc6fa9d27654c6b909de929e542e94a87ffb7b3256190a46", + "l2": "050000ae002033f9c4bdfe3d2597cbf0c86db2b0b3e81a4400ad4c9618372f6e24d89229d9a4be38985f7e04dab53e0bddf32cc9eeb64d7f072e089650b681ba4bb04bcfaeb20023441a15c5ccbbf863e0db5e03c6edc63696b05d83a66e4aa3e10aa1320936fe8357bc250023030020764f186883a88353586c2427bfbe0ff3e5a0f56af414b0c42a5a300fc426ba4d00208229fa7e73d11f6935de9d5aae17ab5ec77d6cff8d8456437a8098bb54aa9b9370c4df069c1a7b70c16cf6409157674c3f8adfd0919f9dd67a254cf167c7e87f05d99649994c006a508b996d11a94f52ae68cca44087bdd69602dfceb92d950cbd9f8a529e49110d4bfe863d449663b0cda71ba29e0aa46f63bbc7b6b054ad8c", + "l3": "6ba92c16abdd010bc8e9a5175d639512f8b270767d4b7198d03a985935e7da6d", + "client_registration_state": "00036964550003696453c5629094a160136e99012cf9c8eb19d9d62f87cadf846636bd175064a78b2d0070617373776f7264", + "client_login_state": "00036964550003696453c5629094a160136e99012cf9c8eb19d9d62f87cadf846636bd175064a78b2d00107078f8e2ddd88c3d37e611ae932d798403e475f52a6695639999f9630635760c51879d4ae4cbd047fbf1ba9c7512c25c8d809486f5e6018dff8c525d9f41f123c1c83fbf2a84c442b079fcacff55b13a4aebf9ba326e992c83b550afbb0c8770617373776f7264", + "server_registration_state": "f431dcb851f3c8202b9dd1a06d8d32434bbab88de4fdd079452faf2359a8d408", + "server_login_state": "72486032f6ff6f079144a891fdcb5ca63ede147f327313437c6bf2fd79d08b1faf03840b6c031f7afb66e2740ae064fc140c9aec2ac42295a6d1201d6ad5cdc641d81a7e3805c996ff9fb15fbcd4eddb528a3622f0f4488bca04bace6d740ee3", + "password_file": "f431dcb851f3c8202b9dd1a06d8d32434bbab88de4fdd079452faf2359a8d4087489b55c78b380db87d664178e5a020eb2f9bbeac0a44f6fb034ccba8de4a934be38985f7e04dab53e0bddf32cc9eeb64d7f072e089650b681ba4bb04bcfaeb20023441a15c5ccbbf863e0db5e03c6edc63696b05d83a66e4aa3e10aa1320936fe8357bc250023030020764f186883a88353586c2427bfbe0ff3e5a0f56af414b0c42a5a300fc426ba4d00208229fa7e73d11f6935de9d5aae17ab5ec77d6cff8d8456437a8098bb54aa9b93", + "export_key": "c2bc61bafeb9ab541fa362dc154c7a07dab8479e486da2daf9408438d9dc562f", + "shared_secret": "41d81a7e3805c996ff9fb15fbcd4eddb528a3622f0f4488bca04bace6d740ee3" } "#; @@ -112,10 +113,10 @@ fn populate_test_vectors(values: &Value) -> TestVectorParameters { server_s_sk: decode(&values, "server_s_sk").unwrap(), server_e_pk: decode(&values, "server_e_pk").unwrap(), server_e_sk: decode(&values, "server_e_sk").unwrap(), + id_u: decode(&values, "id_u").unwrap(), + id_s: decode(&values, "id_s").unwrap(), password: decode(&values, "password").unwrap(), - blinding_factor_raw: decode(&values, "blinding_factor_raw").unwrap(), blinding_factor: decode(&values, "blinding_factor").unwrap(), - pepper: decode(&values, "pepper").unwrap(), oprf_key: decode(&values, "oprf_key").unwrap(), envelope_nonce: decode(&values, "envelope_nonce").unwrap(), client_nonce: decode(&values, "client_nonce").unwrap(), @@ -147,14 +148,9 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> String { s.push_str(format!("\"server_s_sk\": \"{}\",\n", hex::encode(&p.server_s_sk)).as_str()); s.push_str(format!("\"server_e_pk\": \"{}\",\n", hex::encode(&p.server_e_pk)).as_str()); s.push_str(format!("\"server_e_sk\": \"{}\",\n", hex::encode(&p.server_e_sk)).as_str()); + s.push_str(format!("\"id_u\": \"{}\",\n", hex::encode(&p.id_u)).as_str()); + s.push_str(format!("\"id_s\": \"{}\",\n", hex::encode(&p.id_s)).as_str()); s.push_str(format!("\"password\": \"{}\",\n", hex::encode(&p.password)).as_str()); - s.push_str( - format!( - "\"blinding_factor_raw\": \"{}\",\n", - hex::encode(&p.blinding_factor_raw) - ) - .as_str(), - ); s.push_str( format!( "\"blinding_factor\": \"{}\",\n", @@ -162,7 +158,6 @@ fn stringify_test_vectors(p: &TestVectorParameters) -> String { ) .as_str(), ); - s.push_str(format!("\"pepper\": \"{}\",\n", hex::encode(&p.pepper)).as_str()); s.push_str(format!("\"oprf_key\": \"{}\",\n", hex::encode(&p.oprf_key)).as_str()); s.push_str( format!( @@ -239,8 +234,9 @@ where let server_e_kp = CS::generate_random_keypair(&mut rng).unwrap(); let client_s_kp = CS::generate_random_keypair(&mut rng).unwrap(); let client_e_kp = CS::generate_random_keypair(&mut rng).unwrap(); + let id_u = b"idU"; + let id_s = b"idS"; let password = b"password"; - let pepper = b"pepper"; let mut blinding_factor_raw = [0u8; 64]; rng.fill_bytes(&mut blinding_factor_raw); let mut oprf_key_raw = [0u8; 32]; @@ -253,15 +249,16 @@ where rng.fill_bytes(&mut server_nonce); let mut blinding_factor_registration_rng = CycleRng::new(blinding_factor_raw.to_vec()); - let (r1, client_registration) = ClientRegistration::::start( + let (r1, client_registration) = ClientRegistration::::start_with_user_and_server_name( + id_u, + id_s, password, - Some(pepper), &mut blinding_factor_registration_rng, ) .unwrap(); let r1_bytes = r1.serialize().to_vec(); let blinding_factor_bytes = - CS::Group::scalar_as_bytes(&client_registration.blinding_factor).clone(); + CS::Group::scalar_as_bytes(&client_registration.token.blind).clone(); let client_registration_state = client_registration.to_bytes().to_vec(); let mut oprf_key_rng = CycleRng::new(oprf_key_raw.to_vec()); @@ -289,8 +286,13 @@ where client_login_start.extend_from_slice(&client_nonce); let mut client_login_start_rng = CycleRng::new(client_login_start); - let (l1, client_login) = - ClientLogin::::start(password, Some(pepper), &mut client_login_start_rng).unwrap(); + let (l1, client_login) = ClientLogin::::start_with_user_and_server_name( + id_u, + id_s, + password, + &mut client_login_start_rng, + ) + .unwrap(); let l1_bytes = l1.serialize().to_vec(); let client_login_state = client_login.to_bytes().to_vec(); @@ -320,10 +322,10 @@ where server_s_sk: server_s_kp.private().to_arr().to_vec(), server_e_pk: server_e_kp.public().to_arr().to_vec(), server_e_sk: server_e_kp.private().to_arr().to_vec(), + id_u: id_u.to_vec(), + id_s: id_s.to_vec(), password: password.to_vec(), - blinding_factor_raw: blinding_factor_raw.to_vec(), blinding_factor: blinding_factor_bytes.to_vec(), - pepper: pepper.to_vec(), oprf_key: oprf_key_bytes.to_vec(), envelope_nonce: envelope_nonce.to_vec(), client_nonce: client_nonce.to_vec(), @@ -350,14 +352,22 @@ fn generate_test_vectors() { println!("{}", stringify_test_vectors(¶meters)); } +// For fixing the blinding factor +fn postprocess_blinding_factor(_: G::Scalar) -> G::Scalar { + let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap()); + G::from_scalar_slice(GenericArray::from_slice(¶meters.blinding_factor[..])).unwrap() +} + #[test] fn test_r1() -> Result<(), PakeError> { let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap()); - let mut blinding_factor_rng = CycleRng::new(parameters.blinding_factor_raw); - let (r1, client_registration) = ClientRegistration::::start( + let mut rng = OsRng; + let (r1, client_registration) = ClientRegistration::::start_with_user_and_server_name_and_postprocessing( + ¶meters.id_u, + ¶meters.id_s, ¶meters.password, - Some(¶meters.pepper), - &mut blinding_factor_rng, + &mut rng, + postprocess_blinding_factor::<::Group>, ) .unwrap(); assert_eq!(hex::encode(¶meters.r1), hex::encode(r1.serialize())); @@ -436,18 +446,21 @@ fn test_l1() -> Result<(), PakeError> { let parameters = populate_test_vectors(&serde_json::from_str(TEST_VECTOR).unwrap()); let client_login_start = [ - parameters.blinding_factor_raw, + vec![0u8; 64], // FIXME: don't hardcode this parameters.client_e_sk, parameters.client_nonce, ] .concat(); let mut client_login_start_rng = CycleRng::new(client_login_start); - let (l1, client_login) = ClientLogin::::start( - ¶meters.password, - Some(¶meters.pepper), - &mut client_login_start_rng, - ) - .unwrap(); + let (l1, client_login) = + ClientLogin::::start_with_user_and_server_name_and_postprocessing( + ¶meters.id_u, + ¶meters.id_s, + ¶meters.password, + &mut client_login_start_rng, + postprocess_blinding_factor::<::Group>, + ) + .unwrap(); assert_eq!(hex::encode(¶meters.l1), hex::encode(l1.serialize())); assert_eq!( hex::encode(¶meters.client_login_state), @@ -530,18 +543,15 @@ fn test_complete_flow( let mut client_rng = OsRng; let mut server_rng = OsRng; let server_kp = X255193dhNoSlowHash::generate_random_keypair(&mut server_rng)?; - let (register_m1, client_state) = ClientRegistration::::start( - registration_password, - None, - &mut client_rng, - )?; + let (register_m1, client_state) = + ClientRegistration::::start(registration_password, &mut client_rng)?; let (register_m2, server_state) = ServerRegistration::::start(register_m1, &mut server_rng)?; let (register_m3, registration_export_key) = client_state.finish(register_m2, server_kp.public(), &mut client_rng)?; let p_file = server_state.finish(register_m3)?; let (login_m1, client_login_state) = - ClientLogin::::start(login_password, None, &mut client_rng)?; + ClientLogin::::start(login_password, &mut client_rng)?; let (login_m2, server_login_state) = ServerLogin::::start( p_file, &server_kp.private(),