Skip to content

Commit 70754a0

Browse files
committed
Update keypair generation to use derive_auth_keypair
1 parent c73eb96 commit 70754a0

File tree

9 files changed

+577
-553
lines changed

9 files changed

+577
-553
lines changed

src/envelope.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,14 @@ use crate::errors::utils::check_slice_size;
2525
use crate::errors::{InternalError, ProtocolError};
2626
use crate::hash::{Hash, OutputSize, ProxyHash};
2727
use crate::key_exchange::group::KeGroup;
28-
use crate::keypair::{KeyPair, PublicKey};
28+
use crate::keypair::{KeyPair, PublicKey, STR_OPAQUE_DERIVE_AUTH_KEY_PAIR};
2929
use crate::opaque::{bytestrings_from_identifiers, Identifiers};
3030
use crate::serialization::{Input, MacExt};
3131

3232
// Constant string used as salt for HKDF computation
3333
const STR_AUTH_KEY: [u8; 7] = *b"AuthKey";
3434
const STR_EXPORT_KEY: [u8; 9] = *b"ExportKey";
3535
const STR_PRIVATE_KEY: [u8; 10] = *b"PrivateKey";
36-
const STR_OPAQUE_DERIVE_AUTH_KEY_PAIR: [u8; 24] = *b"OPAQUE-DeriveAuthKeyPair";
3736
type NonceLen = U32;
3837

3938
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]

src/key_exchange/traits.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
// of this source tree. You may select, at your option, one of the above-listed
77
// licenses.
88

9-
use digest::core_api::BlockSizeUser;
9+
use digest::core_api::{BlockSizeUser, OutputSizeUser};
1010
use digest::Output;
11-
use generic_array::typenum::{IsLess, Le, NonZero, U256};
11+
use generic_array::typenum::{IsLess, IsLessOrEqual, Le, NonZero, U256};
1212
use generic_array::{ArrayLength, GenericArray};
1313
use rand::{CryptoRng, RngCore};
1414
use zeroize::ZeroizeOnDrop;
@@ -31,12 +31,23 @@ where
3131
type KE2Message: Deserialize + Serialize + ZeroizeOnDrop + Clone;
3232
type KE3Message: Deserialize + Serialize + ZeroizeOnDrop + Clone;
3333

34-
fn generate_ke1<R: RngCore + CryptoRng>(
34+
fn generate_ke1<OprfCs: voprf::CipherSuite, R: RngCore + CryptoRng>(
3535
rng: &mut R,
36-
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>;
36+
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>
37+
where
38+
<OprfCs::Hash as OutputSizeUser>::OutputSize:
39+
IsLess<U256> + IsLessOrEqual<<OprfCs::Hash as BlockSizeUser>::BlockSize>;
3740

3841
#[allow(clippy::too_many_arguments)]
39-
fn generate_ke2<'a, 'b, 'c, 'd, R: RngCore + CryptoRng, S: SecretKey<G>>(
42+
fn generate_ke2<
43+
'a,
44+
'b,
45+
'c,
46+
'd,
47+
OprfCs: voprf::CipherSuite,
48+
R: RngCore + CryptoRng,
49+
S: SecretKey<G>,
50+
>(
4051
rng: &mut R,
4152
l1_bytes: impl Iterator<Item = &'a [u8]>,
4253
l2_bytes: impl Iterator<Item = &'b [u8]>,
@@ -46,7 +57,10 @@ where
4657
id_u: impl Iterator<Item = &'c [u8]>,
4758
id_s: impl Iterator<Item = &'d [u8]>,
4859
context: &[u8],
49-
) -> Result<GenerateKe2Result<Self, D, G>, ProtocolError<S::Error>>;
60+
) -> Result<GenerateKe2Result<Self, D, G>, ProtocolError<S::Error>>
61+
where
62+
<OprfCs::Hash as OutputSizeUser>::OutputSize:
63+
IsLess<U256> + IsLessOrEqual<<OprfCs::Hash as BlockSizeUser>::BlockSize>;
5064

5165
#[allow(clippy::too_many_arguments)]
5266
fn generate_ke3<'a, 'b, 'c, 'd>(

src/key_exchange/tripledh.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ use core::ops::Add;
1212

1313
use derive_where::derive_where;
1414
use digest::core_api::BlockSizeUser;
15-
use digest::{Digest, Output};
15+
use digest::{Digest, Output, OutputSizeUser};
1616
use generic_array::sequence::Concat;
17-
use generic_array::typenum::{IsLess, Le, NonZero, Sum, Unsigned, U1, U2, U256, U32};
17+
use generic_array::typenum::{
18+
IsLess, IsLessOrEqual, Le, NonZero, Sum, Unsigned, U1, U2, U256, U32,
19+
};
1820
use generic_array::{ArrayLength, GenericArray};
1921
use hkdf::{Hkdf, HkdfExtract};
2022
use hmac::{Hmac, Mac};
@@ -161,10 +163,14 @@ where
161163
type KE2Message = Ke2Message<D, KG>;
162164
type KE3Message = Ke3Message<D>;
163165

164-
fn generate_ke1<R: RngCore + CryptoRng>(
166+
fn generate_ke1<OprfCs: voprf::CipherSuite, R: RngCore + CryptoRng>(
165167
rng: &mut R,
166-
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError> {
167-
let client_e_kp = KeyPair::<KG>::generate_random(rng);
168+
) -> Result<(Self::KE1State, Self::KE1Message), ProtocolError>
169+
where
170+
<OprfCs::Hash as OutputSizeUser>::OutputSize:
171+
IsLess<U256> + IsLessOrEqual<<OprfCs::Hash as BlockSizeUser>::BlockSize>,
172+
{
173+
let client_e_kp = KeyPair::<KG>::generate_random::<OprfCs, _>(rng);
168174
let client_nonce = generate_nonce::<R>(rng);
169175

170176
let ke1_message = Ke1Message {
@@ -182,7 +188,15 @@ where
182188
}
183189

184190
#[allow(clippy::type_complexity)]
185-
fn generate_ke2<'a, 'b, 'c, 'd, R: RngCore + CryptoRng, S: SecretKey<KG>>(
191+
fn generate_ke2<
192+
'a,
193+
'b,
194+
'c,
195+
'd,
196+
OprfCs: voprf::CipherSuite,
197+
R: RngCore + CryptoRng,
198+
S: SecretKey<KG>,
199+
>(
186200
rng: &mut R,
187201
serialized_credential_request: impl Iterator<Item = &'a [u8]>,
188202
l2_bytes: impl Iterator<Item = &'b [u8]>,
@@ -192,8 +206,12 @@ where
192206
id_u: impl Iterator<Item = &'c [u8]>,
193207
id_s: impl Iterator<Item = &'d [u8]>,
194208
context: &[u8],
195-
) -> Result<GenerateKe2Result<Self, D, KG>, ProtocolError<S::Error>> {
196-
let server_e_kp = KeyPair::<KG>::generate_random(rng);
209+
) -> Result<GenerateKe2Result<Self, D, KG>, ProtocolError<S::Error>>
210+
where
211+
<OprfCs::Hash as OutputSizeUser>::OutputSize:
212+
IsLess<U256> + IsLessOrEqual<<OprfCs::Hash as BlockSizeUser>::BlockSize>,
213+
{
214+
let server_e_kp = KeyPair::<KG>::generate_random::<OprfCs, _>(rng);
197215
let server_nonce = generate_nonce::<R>(rng);
198216

199217
let mut transcript_hasher = D::new()

src/keypair.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,17 @@
1111
#![allow(unsafe_code)]
1212

1313
use derive_where::derive_where;
14+
use digest::core_api::BlockSizeUser;
15+
use digest::OutputSizeUser;
16+
use generic_array::typenum::{IsLess, IsLessOrEqual, U256};
1417
use generic_array::{ArrayLength, GenericArray};
1518
use rand::{CryptoRng, RngCore};
1619

1720
use crate::errors::{InternalError, ProtocolError};
1821
use crate::key_exchange::group::KeGroup;
1922

23+
pub(crate) const STR_OPAQUE_DERIVE_AUTH_KEY_PAIR: [u8; 33] = *b"OPAQUE-DeriveDiffieHellmanKeyPair";
24+
2025
/// A Keypair trait with public-private verification
2126
#[cfg_attr(
2227
feature = "serde",
@@ -58,8 +63,20 @@ impl<KG: KeGroup, S: SecretKey<KG>> KeyPair<KG, S> {
5863

5964
impl<KG: KeGroup> KeyPair<KG> {
6065
/// Generating a random key pair given a cryptographic rng
61-
pub(crate) fn generate_random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
62-
let sk = KG::random_sk(rng);
66+
pub(crate) fn generate_random<CS: voprf::CipherSuite, R: RngCore + CryptoRng>(
67+
rng: &mut R,
68+
) -> Self
69+
where
70+
<CS::Hash as OutputSizeUser>::OutputSize:
71+
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
72+
{
73+
let mut scalar_bytes = GenericArray::<_, <KG as KeGroup>::SkLen>::default();
74+
rng.fill_bytes(&mut scalar_bytes);
75+
let sk = KG::derive_auth_keypair::<CS>(
76+
GenericArray::clone_from_slice(&scalar_bytes),
77+
&STR_OPAQUE_DERIVE_AUTH_KEY_PAIR,
78+
)
79+
.unwrap();
6380
let pk = KG::public_key(sk);
6481
Self {
6582
pk: PublicKey(pk),
@@ -76,7 +93,11 @@ where
7693
{
7794
/// Test-only strategy returning a proptest Strategy based on
7895
/// generate_random
79-
fn uniform_keypair_strategy() -> proptest::prelude::BoxedStrategy<Self> {
96+
fn uniform_keypair_strategy<CS: voprf::CipherSuite>() -> proptest::prelude::BoxedStrategy<Self>
97+
where
98+
<CS::Hash as OutputSizeUser>::OutputSize:
99+
IsLess<U256> + IsLessOrEqual<<CS::Hash as BlockSizeUser>::BlockSize>,
100+
{
80101
use proptest::prelude::*;
81102
use rand::rngs::StdRng;
82103
use rand::SeedableRng;
@@ -86,7 +107,7 @@ where
86107
any::<[u8; 32]>()
87108
.prop_filter_map("valid random keypair", |seed| {
88109
let mut rng = StdRng::from_seed(seed);
89-
Some(Self::generate_random(&mut rng))
110+
Some(Self::generate_random::<CS, _>(&mut rng))
90111
})
91112
.no_shrink()
92113
.boxed()
@@ -243,15 +264,15 @@ mod tests {
243264

244265
proptest! {
245266
#[test]
246-
fn pub_from_priv(kp in KeyPair::<$point>::uniform_keypair_strategy()) {
267+
fn pub_from_priv(kp in KeyPair::<$point>::uniform_keypair_strategy::<$point>()) {
247268
let pk = kp.public();
248269
let sk = kp.private();
249270
prop_assert_eq!(&sk.public_key()?, pk);
250271
}
251272

252273
#[test]
253-
fn dh(kp1 in KeyPair::<$point>::uniform_keypair_strategy(),
254-
kp2 in KeyPair::<$point>::uniform_keypair_strategy()) {
274+
fn dh(kp1 in KeyPair::<$point>::uniform_keypair_strategy::<$point>(),
275+
kp2 in KeyPair::<$point>::uniform_keypair_strategy::<$point>()) {
255276

256277
let dh1 = kp2.private().diffie_hellman(kp1.public().clone())?;
257278
let dh2 = kp1.private().diffie_hellman(kp2.public().clone())?;
@@ -260,7 +281,7 @@ mod tests {
260281
}
261282

262283
#[test]
263-
fn private_key_slice(kp in KeyPair::<$point>::uniform_keypair_strategy()) {
284+
fn private_key_slice(kp in KeyPair::<$point>::uniform_keypair_strategy::<$point>()) {
264285
let sk_bytes = kp.private().serialize().to_vec();
265286

266287
let kp2 = KeyPair::<$point>::from_private_key_slice(&sk_bytes)?;

src/opaque.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ where
205205
{
206206
/// Generate a new instance of server setup
207207
pub fn new<R: CryptoRng + RngCore>(rng: &mut R) -> Self {
208-
let keypair = KeyPair::generate_random(rng);
208+
let keypair = KeyPair::generate_random::<CS::OprfCs, _>(rng);
209209
Self::new_with_key(rng, keypair)
210210
}
211211
}
@@ -234,7 +234,7 @@ where
234234
Self {
235235
oprf_seed,
236236
keypair,
237-
fake_keypair: KeyPair::<CS::KeGroup>::generate_random(rng),
237+
fake_keypair: KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(rng),
238238
}
239239
}
240240

@@ -542,7 +542,7 @@ where
542542
password: &[u8],
543543
) -> Result<ClientLoginStartResult<CS>, ProtocolError> {
544544
let blind_result = blind::<CS, _>(rng, password)?;
545-
let (ke1_state, ke1_message) = CS::KeyExchange::generate_ke1(rng)?;
545+
let (ke1_state, ke1_message) = CS::KeyExchange::generate_ke1::<CS::OprfCs, _>(rng)?;
546546

547547
let credential_request = CredentialRequest {
548548
blinded_element: blind_result.message,
@@ -757,7 +757,7 @@ where
757757
let credential_response_component =
758758
CredentialResponse::<CS>::serialize_without_ke(&beta, &masking_nonce, &masked_response);
759759

760-
let result = CS::KeyExchange::generate_ke2(
760+
let result = CS::KeyExchange::generate_ke2::<CS::OprfCs, _, _>(
761761
rng,
762762
credential_request_bytes,
763763
credential_response_component,

src/serialization/tests.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ fn server_registration_roundtrip() -> Result<(), ProtocolError> {
153153
// length-MAC_SIZE hmac
154154
mock_envelope_bytes.extend_from_slice(&Output::<OprfHash<CS>>::default());
155155

156-
let mock_client_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
156+
let mock_client_kp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
157157
// serialization order: oprf_key, public key, envelope
158158
let mut bytes = Vec::<u8>::new();
159159
bytes.extend_from_slice(&mock_client_kp.public().serialize());
@@ -233,7 +233,7 @@ fn registration_response_roundtrip() -> Result<(), ProtocolError> {
233233
let pt = random_point::<CS>();
234234
let beta_bytes = CS::KeGroup::serialize_pk(pt);
235235
let mut rng = OsRng;
236-
let skp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
236+
let skp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
237237
let pubkey_bytes = skp.public().serialize();
238238

239239
let mut input = Vec::new();
@@ -288,7 +288,7 @@ fn registration_upload_roundtrip() -> Result<(), ProtocolError> {
288288
RegistrationUploadLen<CS>: ArrayLength<u8>,
289289
{
290290
let mut rng = OsRng;
291-
let skp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
291+
let skp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
292292
let pubkey_bytes = skp.public().serialize();
293293

294294
let mut key = [0u8; 32];
@@ -348,7 +348,7 @@ fn credential_request_roundtrip() -> Result<(), ProtocolError> {
348348
let alpha = random_point::<CS>();
349349
let alpha_bytes = CS::KeGroup::serialize_pk(alpha);
350350

351-
let client_e_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
351+
let client_e_kp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
352352
let mut client_nonce = [0u8; NonceLen::USIZE];
353353
rng.fill_bytes(&mut client_nonce);
354354

@@ -424,7 +424,7 @@ fn credential_response_roundtrip() -> Result<(), ProtocolError> {
424424
vec![0u8; <OprfGroup<CS> as Group>::ElemLen::USIZE + Envelope::<CS>::len()];
425425
rng.fill_bytes(&mut masked_response);
426426

427-
let server_e_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
427+
let server_e_kp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
428428
let mut mac = Output::<OprfHash<CS>>::default();
429429
rng.fill_bytes(&mut mac);
430430
let mut server_nonce = [0u8; NonceLen::USIZE];
@@ -531,7 +531,7 @@ fn client_login_roundtrip() -> Result<(), ProtocolError> {
531531
let pw = b"hunter2";
532532
let mut rng = OsRng;
533533

534-
let client_e_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
534+
let client_e_kp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
535535
let mut client_nonce = [0; NonceLen::USIZE];
536536
rng.fill_bytes(&mut client_nonce);
537537

@@ -590,7 +590,7 @@ fn ke1_message_roundtrip() -> Result<(), ProtocolError> {
590590
{
591591
let mut rng = OsRng;
592592

593-
let client_e_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
593+
let client_e_kp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
594594
let mut client_nonce = vec![0u8; NonceLen::USIZE];
595595
rng.fill_bytes(&mut client_nonce);
596596

@@ -630,7 +630,7 @@ fn ke2_message_roundtrip() -> Result<(), ProtocolError> {
630630
{
631631
let mut rng = OsRng;
632632

633-
let server_e_kp = KeyPair::<CS::KeGroup>::generate_random(&mut rng);
633+
let server_e_kp = KeyPair::<CS::KeGroup>::generate_random::<CS::OprfCs, _>(&mut rng);
634634
let mut mac = Output::<OprfHash<CS>>::default();
635635
rng.fill_bytes(&mut mac);
636636
let mut server_nonce = vec![0u8; NonceLen::USIZE];

0 commit comments

Comments
 (0)