Files
opaque-vx/src/keypair.rs
T

460 lines
15 KiB
Rust
Raw Normal View History

2020-06-05 09:35:14 -07:00
// Copyright (c) Facebook, Inc. and its affiliates.
//
2021-12-03 14:38:11 -08:00
// This source code is licensed under both the MIT license found in the
// LICENSE-MIT file in the root directory of this source tree and the Apache
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
// of this source tree.
2020-06-05 09:35:14 -07:00
//! Contains the keypair types that must be supplied for the OPAQUE API
#![allow(unsafe_code)]
2021-08-22 12:28:19 -07:00
use crate::errors::{InternalError, ProtocolError};
2021-10-25 02:54:32 -07:00
use crate::key_exchange::group::KeGroup;
2021-08-12 06:25:07 +02:00
use core::ops::Deref;
2022-01-04 00:50:40 +01:00
use derive_where::DeriveWhere;
use generic_array::typenum::Unsigned;
2021-07-06 13:27:13 +02:00
use generic_array::{ArrayLength, GenericArray};
2021-02-11 18:10:48 -08:00
use rand::{CryptoRng, RngCore};
2021-04-29 16:22:23 -05:00
use zeroize::Zeroize;
2020-06-05 09:35:14 -07:00
/// A Keypair trait with public-private verification
2021-07-06 14:17:44 +02:00
#[cfg_attr(
2022-01-04 00:50:40 +01:00
feature = "serde",
derive(serde_::Deserialize, serde_::Serialize),
serde(
bound(
deserialize = "S: serde_::Deserialize<'de>",
serialize = "S: serde_::Serialize"
),
crate = "serde_"
)
2021-07-06 14:17:44 +02:00
)]
2022-01-04 00:50:40 +01:00
#[derive(DeriveWhere)]
#[derive_where(Clone, Zeroize(drop))]
#[derive_where(Debug, Eq, Hash, Ord, PartialEq, PartialOrd; S)]
2021-10-25 02:54:32 -07:00
pub struct KeyPair<KG: KeGroup, S: SecretKey<KG> = PrivateKey<KG>> {
pk: PublicKey<KG>,
sk: S,
2021-01-25 13:20:36 -08:00
}
2020-06-05 09:35:14 -07:00
2021-10-25 02:54:32 -07:00
impl<KG: KeGroup, S: SecretKey<KG>> KeyPair<KG, S> {
2020-06-05 09:35:14 -07:00
/// The public key component
2021-10-25 02:54:32 -07:00
pub fn public(&self) -> &PublicKey<KG> {
2021-01-25 13:20:36 -08:00
&self.pk
}
2020-06-05 09:35:14 -07:00
/// The private key component
pub fn private(&self) -> &S {
2021-01-25 13:20:36 -08:00
&self.sk
}
2020-06-05 09:35:14 -07:00
/// Check whether a public key is valid. This is meant to be applied on
/// material provided through the network which fits the key
/// representation (i.e. can be mapped to a curve point), but presents
/// some risk - e.g. small subgroup check
2021-10-25 02:54:32 -07:00
pub(crate) fn check_public_key(key: PublicKey<KG>) -> Result<PublicKey<KG>, InternalError> {
KG::from_pk_slice(GenericArray::from_slice(&key.0)).map(|_| key)
2021-01-25 13:20:36 -08:00
}
2020-06-05 09:35:14 -07:00
/// Obtains a KeyPair from a slice representing the private key
2021-07-20 11:49:37 +02:00
pub fn from_private_key_slice(input: &[u8]) -> Result<Self, ProtocolError<S::Error>> {
2021-07-20 14:16:53 +02:00
Self::from_private_key(S::deserialize(input)?)
}
/// Obtains a KeyPair from a private key
pub fn from_private_key(sk: S) -> Result<Self, ProtocolError<S::Error>> {
let pk = sk.public_key()?;
2021-07-06 14:17:44 +02:00
Ok(Self { pk, sk })
}
}
2021-10-25 02:54:32 -07:00
impl<KG: KeGroup> KeyPair<KG> {
/// Generating a random key pair given a cryptographic rng
2022-01-04 00:50:40 +01:00
pub(crate) fn generate_random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
2021-10-25 02:54:32 -07:00
let sk = KG::random_sk(rng);
let pk = KG::public_key(&sk);
2022-01-04 00:50:40 +01:00
Self {
pk: PublicKey(Key(pk.to_arr())),
2021-10-25 02:54:32 -07:00
sk: PrivateKey(Key(sk)),
2022-01-04 00:50:40 +01:00
}
}
}
2021-08-17 05:11:53 +02:00
#[cfg(test)]
2022-01-04 00:50:40 +01:00
impl<KG: KeGroup> KeyPair<KG> {
/// Test-only strategy returning a proptest Strategy based on
/// generate_random
2021-08-17 05:11:53 +02:00
fn uniform_keypair_strategy() -> proptest::prelude::BoxedStrategy<Self> {
use proptest::prelude::*;
use rand::{rngs::StdRng, SeedableRng};
// The no_shrink is because keypairs should be fixed -- shrinking would cause a different
// keypair to be generated, which appears to not be very useful.
any::<[u8; 32]>()
.prop_filter_map("valid random keypair", |seed| {
let mut rng = StdRng::from_seed(seed);
2022-01-04 00:50:40 +01:00
Some(Self::generate_random(&mut rng))
})
.no_shrink()
.boxed()
}
2020-06-05 09:35:14 -07:00
}
2021-02-11 18:10:48 -08:00
/// A minimalist key type built around a \[u8; 32\]
2021-07-07 13:28:31 +02:00
#[cfg_attr(
2022-01-04 00:50:40 +01:00
feature = "serde",
derive(serde_::Deserialize, serde_::Serialize),
serde(bound = "", crate = "serde_")
2021-07-07 13:28:31 +02:00
)]
2022-01-04 00:50:40 +01:00
#[derive(DeriveWhere)]
#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize(drop))]
2021-07-07 13:28:31 +02:00
pub struct Key<L: ArrayLength<u8>>(GenericArray<u8, L>);
impl<L: ArrayLength<u8>> Deref for Key<L> {
type Target = GenericArray<u8, L>;
2020-06-05 09:35:14 -07:00
fn deref(&self) -> &Self::Target {
&self.0
}
}
2021-06-15 10:48:29 +02:00
// Don't make it implement SizedBytes so that it's not constructible outside of this module.
2021-07-07 13:28:31 +02:00
impl<L: ArrayLength<u8>> Key<L> {
2021-08-17 05:11:53 +02:00
/// Convert to bytes
pub fn to_arr(&self) -> GenericArray<u8, L> {
self.0.clone()
2021-06-15 10:48:29 +02:00
}
}
/// Wrapper around a Key to enforce that it's a private one.
2022-01-04 00:50:40 +01:00
#[cfg_attr(
feature = "serde",
derive(serde_::Deserialize, serde_::Serialize),
serde(bound = "", crate = "serde_")
)]
#[derive(DeriveWhere)]
#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize(drop))]
2021-10-25 02:54:32 -07:00
pub struct PrivateKey<KG: KeGroup>(Key<KG::SkLen>);
2021-07-06 13:27:13 +02:00
2021-07-07 13:31:47 +02:00
// This can't be derived because of the use of a generic parameter
2021-10-25 02:54:32 -07:00
impl<KG: KeGroup> Deref for PrivateKey<KG> {
type Target = Key<KG::SkLen>;
2021-06-15 10:48:29 +02:00
fn deref(&self) -> &Self::Target {
2021-07-07 13:28:31 +02:00
&self.0
2021-07-06 13:27:13 +02:00
}
}
2021-10-25 02:54:32 -07:00
impl<KG: KeGroup> PrivateKey<KG> {
2021-08-17 05:11:53 +02:00
/// Convert from bytes
2021-10-25 02:54:32 -07:00
pub fn from_arr(key_bytes: GenericArray<u8, KG::SkLen>) -> Self {
2021-08-17 05:11:53 +02:00
PrivateKey(Key(key_bytes))
2020-06-05 09:35:14 -07:00
}
2021-08-17 05:11:53 +02:00
/// Convert from slice
2021-08-22 12:28:19 -07:00
pub fn from_bytes(key_bytes: &[u8]) -> Result<Self, InternalError> {
2021-10-25 02:54:32 -07:00
if key_bytes.len() == KG::SkLen::USIZE {
2021-08-17 05:11:53 +02:00
Ok(Self::from_arr(GenericArray::from_slice(key_bytes).clone()))
} else {
2021-08-22 12:28:19 -07:00
Err(InternalError::InvalidByteSequence)
2021-08-17 05:11:53 +02:00
}
2021-06-15 10:48:29 +02:00
}
}
/// A trait specifying the requirements for a private key container
2021-10-25 02:54:32 -07:00
pub trait SecretKey<KG: KeGroup>: Clone + Sized + Zeroize {
2021-08-22 12:28:19 -07:00
/// Custom error type that can be passed down to `InternalError::Custom`
2021-07-20 11:49:37 +02:00
type Error;
2022-01-04 00:50:40 +01:00
/// Serialization size in bytes.
type Len: ArrayLength<u8>;
2021-07-20 11:49:37 +02:00
/// Diffie-Hellman key exchange implementation
2022-01-04 00:50:40 +01:00
fn diffie_hellman(
&self,
pk: PublicKey<KG>,
) -> Result<GenericArray<u8, KG::PkLen>, InternalError<Self::Error>>;
/// Returns public key from private key
2021-10-25 02:54:32 -07:00
fn public_key(&self) -> Result<PublicKey<KG>, InternalError<Self::Error>>;
/// Serialization into bytes
2022-01-04 00:50:40 +01:00
fn serialize(&self) -> GenericArray<u8, Self::Len>;
/// Deserialization from bytes
2021-08-22 12:28:19 -07:00
fn deserialize(input: &[u8]) -> Result<Self, InternalError<Self::Error>>;
}
2021-10-25 02:54:32 -07:00
impl<KG: KeGroup> SecretKey<KG> for PrivateKey<KG> {
2021-08-12 06:25:07 +02:00
type Error = core::convert::Infallible;
2022-01-04 00:50:40 +01:00
type Len = KG::SkLen;
2021-07-20 11:49:37 +02:00
2022-01-04 00:50:40 +01:00
fn diffie_hellman(
&self,
pk: PublicKey<KG>,
) -> Result<GenericArray<u8, KG::PkLen>, InternalError> {
2021-10-25 02:54:32 -07:00
let pk = KG::from_pk_slice(&pk)?;
2022-01-04 00:50:40 +01:00
Ok(pk.diffie_hellman(self))
}
2021-10-25 02:54:32 -07:00
fn public_key(&self) -> Result<PublicKey<KG>, InternalError> {
Ok(PublicKey(Key(KG::public_key(&self.0).to_arr())))
}
2022-01-04 00:50:40 +01:00
fn serialize(&self) -> GenericArray<u8, Self::Len> {
self.to_arr()
}
2021-08-22 12:28:19 -07:00
fn deserialize(input: &[u8]) -> Result<Self, InternalError> {
PrivateKey::from_bytes(input).map_err(InternalError::from)
}
}
2021-06-15 10:48:29 +02:00
/// Wrapper around a Key to enforce that it's a public one.
2022-01-04 00:50:40 +01:00
#[cfg_attr(
feature = "serde",
derive(serde_::Deserialize, serde_::Serialize),
serde(bound = "", crate = "serde_")
)]
#[derive(DeriveWhere)]
#[derive_where(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize(drop))]
2021-10-25 02:54:32 -07:00
pub struct PublicKey<KG: KeGroup>(Key<KG::PkLen>);
2021-06-15 10:48:29 +02:00
2021-10-25 02:54:32 -07:00
impl<KG: KeGroup> Deref for PublicKey<KG> {
type Target = Key<KG::PkLen>;
2021-06-15 10:48:29 +02:00
fn deref(&self) -> &Self::Target {
2021-07-07 13:28:31 +02:00
&self.0
2021-06-15 10:48:29 +02:00
}
}
2021-10-25 02:54:32 -07:00
impl<KG: KeGroup> PublicKey<KG> {
2021-08-17 05:11:53 +02:00
/// Convert from bytes
2021-10-25 02:54:32 -07:00
pub fn from_arr(key_bytes: GenericArray<u8, KG::PkLen>) -> Self {
2021-08-17 05:11:53 +02:00
Self(Key(key_bytes))
2021-06-15 10:48:29 +02:00
}
2021-08-17 05:11:53 +02:00
/// Convert from slice
2021-08-22 12:28:19 -07:00
pub fn from_bytes(key_bytes: &[u8]) -> Result<Self, InternalError> {
2021-10-25 02:54:32 -07:00
if key_bytes.len() == KG::PkLen::USIZE {
2021-08-17 05:11:53 +02:00
Ok(Self::from_arr(GenericArray::from_slice(key_bytes).clone()))
} else {
2021-08-22 12:28:19 -07:00
Err(InternalError::InvalidByteSequence)
2021-08-17 05:11:53 +02:00
}
2020-06-05 09:35:14 -07:00
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::errors::*;
2021-08-12 06:25:07 +02:00
use core::slice::from_raw_parts;
use generic_array::typenum::Unsigned;
use rand::rngs::OsRng;
#[test]
fn test_zeroize_key() -> Result<(), ProtocolError> {
2022-01-04 00:50:40 +01:00
fn inner<G: KeGroup>() -> Result<(), ProtocolError> {
let key_len = G::PkLen::USIZE;
let mut key = Key::<G::PkLen>(GenericArray::clone_from_slice(&alloc::vec![
2021-07-07 13:28:31 +02:00
1u8;
key_len
2022-01-04 00:50:40 +01:00
]));
let ptr = key.as_ptr();
Zeroize::zeroize(&mut key);
2022-01-04 00:50:40 +01:00
let bytes = unsafe { from_raw_parts(ptr, key_len) };
assert!(bytes.iter().all(|&x| x == 0));
2022-01-04 00:50:40 +01:00
Ok(())
}
#[cfg(feature = "ristretto255")]
inner::<curve25519_dalek::ristretto::RistrettoPoint>()?;
#[cfg(feature = "p256")]
inner::<p256_::PublicKey>()?;
Ok(())
}
#[test]
2022-01-04 00:50:40 +01:00
fn test_zeroize_keypair() {
fn inner<G: KeGroup>() {
let mut rng = OsRng;
let mut keypair = KeyPair::<G>::generate_random(&mut rng);
let pk_ptr = keypair.pk.as_ptr();
let sk_ptr = keypair.sk.as_ptr();
let pk_len = G::PkLen::USIZE;
let sk_len = G::SkLen::USIZE;
Zeroize::zeroize(&mut keypair);
let pk_bytes = unsafe { from_raw_parts(pk_ptr, pk_len) };
let sk_bytes = unsafe { from_raw_parts(sk_ptr, sk_len) };
assert!(pk_bytes.iter().all(|&x| x == 0));
assert!(sk_bytes.iter().all(|&x| x == 0));
}
2022-01-04 00:50:40 +01:00
#[cfg(feature = "ristretto255")]
inner::<curve25519_dalek::ristretto::RistrettoPoint>();
#[cfg(feature = "p256")]
inner::<p256_::PublicKey>();
}
2022-01-04 00:50:40 +01:00
macro_rules! test {
($mod:ident, $point:ty) => {
mod $mod {
use super::*;
use proptest::prelude::*;
2022-01-04 00:50:40 +01:00
proptest! {
#[test]
fn check(kp in KeyPair::<$point>::uniform_keypair_strategy()) {
let pk = kp.public();
prop_assert!(KeyPair::<$point>::check_public_key(pk.clone()).is_ok());
}
2022-01-04 00:50:40 +01:00
#[test]
fn pub_from_priv(kp in KeyPair::<$point>::uniform_keypair_strategy()) {
let pk = kp.public();
let sk = kp.private();
prop_assert_eq!(&sk.public_key()?, pk);
}
2020-06-12 18:46:08 -04:00
2022-01-04 00:50:40 +01:00
#[test]
fn dh(kp1 in KeyPair::<$point>::uniform_keypair_strategy(),
kp2 in KeyPair::<$point>::uniform_keypair_strategy()) {
2020-06-12 18:46:08 -04:00
2022-01-04 00:50:40 +01:00
let dh1 = kp2.private().diffie_hellman(kp1.public().clone())?;
let dh2 = kp1.private().diffie_hellman(kp2.public().clone())?;
2022-01-04 00:50:40 +01:00
prop_assert_eq!(dh1, dh2);
}
2022-01-04 00:50:40 +01:00
#[test]
fn private_key_slice(kp in KeyPair::<$point>::uniform_keypair_strategy()) {
let sk_bytes = kp.private().to_vec();
2022-01-04 00:50:40 +01:00
let kp2 = KeyPair::<$point>::from_private_key_slice(&sk_bytes)?;
let kp2_private_bytes = kp2.private().to_vec();
prop_assert_eq!(sk_bytes, kp2_private_bytes);
}
}
}
};
}
2021-07-20 14:16:59 +02:00
2022-01-04 00:50:40 +01:00
#[cfg(feature = "ristretto255")]
test!(ristretto, curve25519_dalek::ristretto::RistrettoPoint);
#[cfg(feature = "p256")]
test!(p256, p256_::PublicKey);
2021-07-20 14:16:59 +02:00
#[test]
2021-08-12 06:25:07 +02:00
fn remote_key() {
2021-07-20 14:16:59 +02:00
use crate::{
CipherSuite, ClientLogin, ClientLoginFinishParameters, ClientLoginFinishResult,
ClientLoginStartResult, ClientRegistration, ClientRegistrationFinishParameters,
ClientRegistrationFinishResult, ClientRegistrationStartResult, ServerLogin,
ServerLoginStartParameters, ServerLoginStartResult, ServerRegistration,
ServerRegistrationStartResult, ServerSetup,
};
2022-01-04 00:50:40 +01:00
#[cfg(feature = "ristretto255")]
use curve25519_dalek::ristretto::RistrettoPoint as KeCurve;
#[cfg(not(feature = "ristretto255"))]
use p256_::PublicKey as KeCurve;
2021-07-20 14:16:59 +02:00
use rand::rngs::OsRng;
struct Default;
impl CipherSuite for Default {
2022-01-04 00:50:40 +01:00
#[cfg(feature = "ristretto255")]
type OprfGroup = KeCurve;
#[cfg(not(feature = "ristretto255"))]
type OprfGroup = p256_::ProjectivePoint;
type KeGroup = KeCurve;
2021-07-20 14:16:59 +02:00
type KeyExchange = crate::key_exchange::tripledh::TripleDH;
2022-01-04 00:50:40 +01:00
#[cfg(feature = "ristretto255")]
2021-07-20 14:16:59 +02:00
type Hash = sha2::Sha512;
2022-01-04 00:50:40 +01:00
#[cfg(not(feature = "ristretto255"))]
type Hash = sha2::Sha256;
2021-07-20 14:16:59 +02:00
type SlowHash = crate::slow_hash::NoOpHash;
}
#[derive(Clone, Zeroize)]
2022-01-04 00:50:40 +01:00
struct RemoteKey(PrivateKey<KeCurve>);
2021-07-20 14:16:59 +02:00
2022-01-04 00:50:40 +01:00
impl SecretKey<KeCurve> for RemoteKey {
2021-08-12 06:25:07 +02:00
type Error = core::convert::Infallible;
2022-01-04 00:50:40 +01:00
type Len = <KeCurve as KeGroup>::SkLen;
2021-07-20 14:16:59 +02:00
fn diffie_hellman(
&self,
2022-01-04 00:50:40 +01:00
pk: PublicKey<KeCurve>,
) -> Result<GenericArray<u8, <KeCurve as KeGroup>::PkLen>, InternalError<Self::Error>>
{
2021-07-20 14:16:59 +02:00
self.0.diffie_hellman(pk)
}
2022-01-04 00:50:40 +01:00
fn public_key(&self) -> Result<PublicKey<KeCurve>, InternalError<Self::Error>> {
2021-07-20 14:16:59 +02:00
self.0.public_key()
}
2022-01-04 00:50:40 +01:00
fn serialize(&self) -> GenericArray<u8, Self::Len> {
2021-07-20 14:16:59 +02:00
self.0.serialize()
}
2021-08-22 12:28:19 -07:00
fn deserialize(input: &[u8]) -> Result<Self, InternalError<Self::Error>> {
2021-07-20 14:16:59 +02:00
PrivateKey::deserialize(input).map(Self)
}
}
const PASSWORD: &str = "password";
2022-01-04 00:50:40 +01:00
let sk = KeCurve::random_sk(&mut OsRng);
2021-10-25 02:54:32 -07:00
let sk = RemoteKey(PrivateKey(Key(sk)));
2021-08-12 06:25:07 +02:00
let keypair = KeyPair::from_private_key(sk).unwrap();
2021-07-20 14:16:59 +02:00
2022-01-04 00:50:40 +01:00
let server_setup = ServerSetup::<Default, RemoteKey>::new_with_key(&mut OsRng, keypair);
2021-07-20 14:16:59 +02:00
let ClientRegistrationStartResult {
message,
state: client,
2021-08-12 06:25:07 +02:00
} = ClientRegistration::<Default>::start(&mut OsRng, PASSWORD.as_bytes()).unwrap();
2021-07-30 14:00:23 +02:00
let ServerRegistrationStartResult { message, .. } =
2021-08-12 06:25:07 +02:00
ServerRegistration::start(&server_setup, message, &[]).unwrap();
let ClientRegistrationFinishResult { message, .. } = client
.finish(
&mut OsRng,
message,
2021-09-02 11:28:21 +02:00
ClientRegistrationFinishParameters::default(),
2021-08-12 06:25:07 +02:00
)
.unwrap();
2021-07-20 14:16:59 +02:00
let file = ServerRegistration::finish(message);
let ClientLoginStartResult {
message,
state: client,
2021-08-12 06:25:07 +02:00
} = ClientLogin::<Default>::start(&mut OsRng, PASSWORD.as_bytes()).unwrap();
2021-07-20 14:16:59 +02:00
let ServerLoginStartResult {
message,
state: server,
2021-07-30 12:54:16 +02:00
..
2021-07-20 14:16:59 +02:00
} = ServerLogin::start(
&mut OsRng,
&server_setup,
Some(file),
message,
&[],
ServerLoginStartParameters::default(),
2021-08-12 06:25:07 +02:00
)
.unwrap();
let ClientLoginFinishResult { message, .. } = client
2021-09-02 11:28:21 +02:00
.finish(message, ClientLoginFinishParameters::default())
2021-08-12 06:25:07 +02:00
.unwrap();
server.finish(message).unwrap();
2021-07-20 14:16:59 +02:00
}
}