Skip to content

Commit

Permalink
Revamp KeGroup trait
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Jan 5, 2022
1 parent f6bf97e commit df4bb8d
Show file tree
Hide file tree
Showing 19 changed files with 513 additions and 395 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,15 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
args: --all-targets -- -D warnings
args: --all-targets --features p256,slow-hash,std,x25519 -- -D warnings

- name: Run cargo doc
uses: actions-rs/cargo@v1
env:
RUSTDOCFLAGS: -D warnings
with:
command: doc
args: --no-deps --document-private-items --features p256,slow-hash,std
args: --no-deps --document-private-items --features p256,slow-hash,std,x25519

format:
name: cargo fmt
Expand Down
4 changes: 2 additions & 2 deletions benches/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct Default;
#[cfg(feature = "ristretto255")]
impl CipherSuite for Default {
type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
type KeGroup = opaque_ke::Ristretto255;
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
type Hash = sha2::Sha512;
type SlowHash = opaque_ke::slow_hash::NoOpHash;
Expand All @@ -37,7 +37,7 @@ impl CipherSuite for Default {
#[cfg(not(feature = "ristretto255"))]
impl CipherSuite for Default {
type OprfGroup = p256_::ProjectivePoint;
type KeGroup = p256_::PublicKey;
type KeGroup = p256_::NistP256;
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
type Hash = sha2::Sha256;
type SlowHash = opaque_ke::slow_hash::NoOpHash;
Expand Down
4 changes: 2 additions & 2 deletions examples/digital_locker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ struct Default;
#[cfg(feature = "ristretto255")]
impl CipherSuite for Default {
type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
type KeGroup = opaque_ke::Ristretto255;
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
type Hash = sha2::Sha512;
type SlowHash = opaque_ke::slow_hash::NoOpHash;
Expand All @@ -59,7 +59,7 @@ impl CipherSuite for Default {
#[cfg(not(feature = "ristretto255"))]
impl CipherSuite for Default {
type OprfGroup = p256_::ProjectivePoint;
type KeGroup = p256_::PublicKey;
type KeGroup = p256_::NistP256;
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
type Hash = sha2::Sha256;
type SlowHash = opaque_ke::slow_hash::NoOpHash;
Expand Down
4 changes: 2 additions & 2 deletions examples/simple_login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ struct Default;
#[cfg(feature = "ristretto255")]
impl CipherSuite for Default {
type OprfGroup = curve25519_dalek::ristretto::RistrettoPoint;
type KeGroup = curve25519_dalek::ristretto::RistrettoPoint;
type KeGroup = opaque_ke::Ristretto255;
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
type Hash = sha2::Sha512;
type SlowHash = opaque_ke::slow_hash::NoOpHash;
Expand All @@ -53,7 +53,7 @@ impl CipherSuite for Default {
#[cfg(not(feature = "ristretto255"))]
impl CipherSuite for Default {
type OprfGroup = p256_::ProjectivePoint;
type KeGroup = p256_::PublicKey;
type KeGroup = p256_::NistP256;
type KeyExchange = opaque_ke::key_exchange::tripledh::TripleDH;
type Hash = sha2::Sha256;
type SlowHash = opaque_ke::slow_hash::NoOpHash;
Expand Down
26 changes: 17 additions & 9 deletions src/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@ const STR_PRIVATE_KEY: [u8; 10] = *b"PrivateKey";
const STR_OPAQUE_DERIVE_AUTH_KEY_PAIR: [u8; 24] = *b"OPAQUE-DeriveAuthKeyPair";
type NonceLen = U32;

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Zeroize)]
#[zeroize(drop)]
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub(crate) enum InnerEnvelopeMode {
Zero = 0,
Internal = 1,
}

impl Zeroize for InnerEnvelopeMode {
fn zeroize(&mut self) {
*self = Self::Zero
}
}

impl TryFrom<u8> for InnerEnvelopeMode {
type Error = ProtocolError;
fn try_from(x: u8) -> Result<Self, Self::Error> {
Expand All @@ -69,7 +74,7 @@ where
<<CS::Hash as CoreProxy>::Core as BlockSizeUser>::BlockSize: IsLess<U256>,
Le<<<CS::Hash as CoreProxy>::Core as BlockSizeUser>::BlockSize, U256>: NonZero,
{
mode: InnerEnvelopeMode,
pub(crate) mode: InnerEnvelopeMode,
nonce: GenericArray<u8, NonceLen>,
hmac: Output<CS::Hash>,
}
Expand Down Expand Up @@ -136,12 +141,13 @@ where
build_inner_envelope_internal::<CS>(randomized_pwd_hasher.clone(), nonce)?,
);

let server_s_pk_bytes = server_s_pk.to_bytes();
let (id_u, id_s) = bytestrings_from_identifiers::<CS::KeGroup>(
ids,
client_s_pk.to_arr(),
server_s_pk.to_arr(),
client_s_pk.to_bytes(),
server_s_pk_bytes.clone(),
)?;
let aad = construct_aad(id_u.iter(), id_s.iter(), server_s_pk);
let aad = construct_aad(id_u.iter(), id_s.iter(), &server_s_pk_bytes);

let result = Self::seal_raw(randomized_pwd_hasher, nonce, aad, mode)?;
Ok((
Expand Down Expand Up @@ -206,12 +212,13 @@ where
}
};

let server_s_pk_bytes = server_s_pk.to_bytes();
let (id_u, id_s) = bytestrings_from_identifiers::<CS::KeGroup>(
optional_ids,
client_static_keypair.public().to_arr(),
server_s_pk.to_arr(),
client_static_keypair.public().to_bytes(),
server_s_pk_bytes.clone(),
)?;
let aad = construct_aad(id_u.iter(), id_s.iter(), &server_s_pk);
let aad = construct_aad(id_u.iter(), id_s.iter(), &server_s_pk_bytes);

let opened = self.open_raw(randomized_pwd_hasher, aad)?;

Expand Down Expand Up @@ -318,6 +325,7 @@ where
.expand(&nonce.concat(STR_PRIVATE_KEY.into()), &mut keypair_seed)
.map_err(|_| InternalError::HkdfError)?;
let client_static_keypair = KeyPair::<CS::KeGroup>::from_private_key_slice(
// TODO: Use `KeGroup` instead of `OprfGroup` here.
&CS::OprfGroup::scalar_as_bytes(CS::OprfGroup::hash_to_scalar::<CS::Hash, _, _>(
[keypair_seed.as_slice()],
GenericArray::from(STR_OPAQUE_DERIVE_AUTH_KEY_PAIR),
Expand Down
27 changes: 20 additions & 7 deletions src/key_exchange/group/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,39 @@ use rand::{CryptoRng, RngCore};
use crate::errors::InternalError;

/// A group representation for use in the key exchange
pub trait KeGroup: Sized + Clone {
pub trait KeGroup {
/// Public key
type Pk: Clone + Sized;
/// Length of the public key
type PkLen: ArrayLength<u8> + 'static;
/// Secret key
type Sk: Clone + Sized;
/// Length of the secret key
type SkLen: ArrayLength<u8> + 'static;

/// Serializes `self`
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen>;

/// Return a public key from its fixed-length bytes representation
fn from_pk_slice(element_bits: &GenericArray<u8, Self::PkLen>) -> Result<Self, InternalError>;
fn deserialize_pk(bytes: &GenericArray<u8, Self::PkLen>) -> Result<Self::Pk, InternalError>;

/// Generate a random secret key
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> GenericArray<u8, Self::SkLen>;
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk;

/// Return a public key from its secret key
fn public_key(sk: &GenericArray<u8, Self::SkLen>) -> Self;
fn public_key(sk: &Self::Sk) -> Self::Pk;

/// Diffie-Hellman key exchange
fn diffie_hellman(pk: &Self::Pk, sk: &Self::Sk) -> GenericArray<u8, Self::PkLen>;

/// Zeroize secret key on drop.
fn zeroize_sk_on_drop(sk: &mut Self::Sk);

/// Serializes `self`
fn to_arr(&self) -> GenericArray<u8, Self::PkLen>;
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen>;

/// Diffie-Hellman key exchange
fn diffie_hellman(&self, sk: &GenericArray<u8, Self::SkLen>) -> GenericArray<u8, Self::PkLen>;
/// Return a public key from its fixed-length bytes representation
fn deserialize_sk(bytes: &GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError>;
}

#[cfg(feature = "p256")]
Expand Down
51 changes: 28 additions & 23 deletions src/key_exchange/group/p256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,49 @@

use generic_array::typenum::{U32, U33};
use generic_array::GenericArray;
use p256_::elliptic_curve::group::GroupEncoding;
use p256_::elliptic_curve::sec1::ToEncodedPoint;
use p256_::elliptic_curve::{PublicKey, SecretKey};
use p256_::NistP256;
use p256::elliptic_curve::group::GroupEncoding;
use p256::elliptic_curve::sec1::ToEncodedPoint;
use p256::elliptic_curve::{PublicKey, SecretKey};
use p256::NistP256;
use rand::{CryptoRng, RngCore};

use super::KeGroup;
use crate::errors::InternalError;

impl KeGroup for PublicKey<NistP256> {
impl KeGroup for NistP256 {
type Pk = PublicKey<Self>;
type PkLen = U33;
type Sk = SecretKey<Self>;
type SkLen = U32;
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
GenericArray::clone_from_slice(pk.to_encoded_point(true).as_bytes())
}

fn deserialize_pk(bytes: &GenericArray<u8, Self::PkLen>) -> Result<Self::Pk, InternalError> {
Self::Pk::from_sec1_bytes(bytes).map_err(|_| InternalError::PointError)
}

fn from_pk_slice(element_bits: &GenericArray<u8, Self::PkLen>) -> Result<Self, InternalError> {
Self::from_sec1_bytes(element_bits).map_err(|_| InternalError::PointError)
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
SecretKey::<NistP256>::random(rng)
}

fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> GenericArray<u8, Self::SkLen> {
SecretKey::<NistP256>::random(rng).to_be_bytes()
fn public_key(sk: &Self::Sk) -> Self::Pk {
sk.public_key()
}

fn public_key(sk: &GenericArray<u8, Self::SkLen>) -> Self {
SecretKey::<NistP256>::from_be_bytes(sk)
.unwrap()
.public_key()
fn diffie_hellman(pk: &Self::Pk, sk: &Self::Sk) -> GenericArray<u8, Self::PkLen> {
(pk.to_projective() * sk.to_nonzero_scalar().as_ref())
.to_affine()
.to_bytes()
}

fn to_arr(&self) -> GenericArray<u8, Self::PkLen> {
GenericArray::clone_from_slice(self.to_encoded_point(true).as_bytes())
fn zeroize_sk_on_drop(_: &mut Self::Sk) {}

fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
sk.to_be_bytes()
}

fn diffie_hellman(&self, sk: &GenericArray<u8, Self::SkLen>) -> GenericArray<u8, Self::PkLen> {
(self.to_projective()
* SecretKey::<NistP256>::from_be_bytes(sk)
.unwrap()
.to_nonzero_scalar()
.as_ref())
.to_affine()
.to_bytes()
fn deserialize_sk(bytes: &GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError> {
Self::Sk::from_be_bytes(bytes).map_err(|_| InternalError::PointError)
}
}
46 changes: 34 additions & 12 deletions src/key_exchange/group/ristretto255.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,31 @@ use curve25519_dalek::scalar::Scalar;
use generic_array::typenum::U32;
use generic_array::GenericArray;
use rand::{CryptoRng, RngCore};
use zeroize::Zeroize;

use super::KeGroup;
use crate::errors::InternalError;

impl KeGroup for RistrettoPoint {
/// Implementation for Ristretto255.
pub struct Ristretto255;

impl KeGroup for Ristretto255 {
type Pk = RistrettoPoint;
type PkLen = U32;
type Sk = Scalar;
type SkLen = U32;

fn from_pk_slice(element_bits: &GenericArray<u8, Self::PkLen>) -> Result<Self, InternalError> {
CompressedRistretto::from_slice(element_bits)
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
pk.compress().to_bytes().into()
}

fn deserialize_pk(bytes: &GenericArray<u8, Self::PkLen>) -> Result<Self::Pk, InternalError> {
CompressedRistretto::from_slice(bytes)
.decompress()
.ok_or(InternalError::PointError)
}

fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> GenericArray<u8, Self::SkLen> {
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
loop {
let scalar = {
#[cfg(not(test))]
Expand All @@ -47,21 +57,33 @@ impl KeGroup for RistrettoPoint {
}
};

if scalar != Scalar::zero() {
break scalar.to_bytes().into();
if scalar != Scalar::zero() && scalar.is_canonical() {
break scalar;
}
}
}

fn public_key(sk: &GenericArray<u8, Self::SkLen>) -> Self {
RISTRETTO_BASEPOINT_POINT * Scalar::from_bits(*sk.as_ref())
fn public_key(sk: &Self::Sk) -> Self::Pk {
RISTRETTO_BASEPOINT_POINT * sk
}

fn diffie_hellman(pk: &Self::Pk, sk: &Self::Sk) -> GenericArray<u8, Self::PkLen> {
Self::serialize_pk(&(pk * sk))
}

fn zeroize_sk_on_drop(sk: &mut Self::Sk) {
sk.zeroize()
}

fn to_arr(&self) -> GenericArray<u8, Self::PkLen> {
self.compress().to_bytes().into()
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
sk.to_bytes().into()
}

fn diffie_hellman(&self, sk: &GenericArray<u8, Self::SkLen>) -> GenericArray<u8, Self::SkLen> {
(self * Scalar::from_bits(*sk.as_ref())).to_arr()
fn deserialize_sk(bytes: &GenericArray<u8, Self::PkLen>) -> Result<Self::Sk, InternalError> {
// TODO: When we implement `hash_to_field` we can re-enable this again.
//Scalar::from_canonical_bytes((*bytes).into()).ok_or(InternalError::
// PointError)

Ok(Scalar::from_bits((*bytes).into()))
}
}
Loading

0 comments on commit df4bb8d

Please sign in to comment.