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