Remove Zeroize Tests (#381)
* Remove Zeroize tests * Remove `Zeroize` requirements from `Group::Pk` * Remove `Copy` requirements from `Group::Pk` * Change to `ZeroizeOnDrop` requirements for `Group::Sk` * Add note why we don't use `elliptic_curve::PublicKey`
This commit is contained in:
@@ -16,7 +16,7 @@ use generic_array::GenericArray;
|
||||
use generic_array::typenum::U32;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use subtle::ConstantTimeEq;
|
||||
use zeroize::Zeroize;
|
||||
use zeroize::ZeroizeOnDrop;
|
||||
|
||||
use super::Group;
|
||||
use crate::errors::{InternalError, ProtocolError};
|
||||
@@ -33,7 +33,7 @@ impl Group for Curve25519 {
|
||||
type Sk = Scalar;
|
||||
type SkLen = U32;
|
||||
|
||||
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
pk.0.to_bytes().into()
|
||||
}
|
||||
|
||||
@@ -56,11 +56,11 @@ impl Group for Curve25519 {
|
||||
Ok(Scalar(scalar::clamp_integer(seed.into())))
|
||||
}
|
||||
|
||||
fn public_key(sk: Self::Sk) -> Self::Pk {
|
||||
fn public_key(sk: &Self::Sk) -> Self::Pk {
|
||||
NonIdentity(MontgomeryPoint::mul_base_clamped(sk.0))
|
||||
}
|
||||
|
||||
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
sk.0.into()
|
||||
}
|
||||
|
||||
@@ -72,14 +72,14 @@ impl Group for Curve25519 {
|
||||
}
|
||||
|
||||
impl DiffieHellman<Curve25519> for Scalar {
|
||||
fn diffie_hellman(self, pk: NonIdentity) -> GenericArray<u8, U32> {
|
||||
Curve25519::serialize_pk(NonIdentity(pk.0.mul_clamped(self.0)))
|
||||
fn diffie_hellman(&self, pk: &NonIdentity) -> GenericArray<u8, U32> {
|
||||
Curve25519::serialize_pk(&NonIdentity(pk.0.mul_clamped(self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Non-identity point wrapper for [`MontgomeryPoint`].
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct NonIdentity(
|
||||
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_pk"))]
|
||||
MontgomeryPoint,
|
||||
@@ -113,7 +113,7 @@ where
|
||||
|
||||
/// Curve25519 scalar.
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, ZeroizeOnDrop)]
|
||||
pub struct Scalar(
|
||||
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_sk"))] [u8; 32],
|
||||
);
|
||||
@@ -142,28 +142,6 @@ where
|
||||
.map_err(D::Error::custom)
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Test Implementations //
|
||||
//===================== //
|
||||
//////////////////////////
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::serialization::AssertZeroized;
|
||||
|
||||
#[cfg(test)]
|
||||
impl AssertZeroized for NonIdentity {
|
||||
fn assert_zeroized(&self) {
|
||||
assert_eq!(self.0, MontgomeryPoint::default());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl AssertZeroized for Scalar {
|
||||
fn assert_zeroized(&self) {
|
||||
assert_eq!(*self, Scalar(<_>::default()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_zero_scalar() {
|
||||
use std::vec;
|
||||
|
||||
@@ -21,7 +21,7 @@ use generic_array::GenericArray;
|
||||
use generic_array::sequence::Concat;
|
||||
use generic_array::typenum::{U32, U64};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use zeroize::Zeroize;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
use super::Group;
|
||||
use crate::ciphersuite::CipherSuite;
|
||||
@@ -41,7 +41,7 @@ impl Group for Ed25519 {
|
||||
type Sk = SigningKey;
|
||||
type SkLen = U32;
|
||||
|
||||
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
pk.compressed.0.into()
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@ impl Group for Ed25519 {
|
||||
Ok(SigningKey::from_bytes(seed.into()))
|
||||
}
|
||||
|
||||
fn public_key(sk: Self::Sk) -> Self::Pk {
|
||||
fn public_key(sk: &Self::Sk) -> Self::Pk {
|
||||
sk.verifying_key
|
||||
}
|
||||
|
||||
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
sk.sk.into()
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ impl serde::Serialize for VerifyingKey {
|
||||
/// Ed25519 signing key.
|
||||
// We store the `ExpandedSecret` in memory to avoid computing it on demand and then discarding it
|
||||
// again.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Zeroize)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, ZeroizeOnDrop)]
|
||||
pub struct SigningKey {
|
||||
// `ed25519_dalek::SigningKey` doesn't implement `Zeroize`. See
|
||||
// https://github.com/dalek-cryptography/curve25519-dalek/pull/747
|
||||
@@ -428,44 +428,6 @@ impl Zeroize for Signature {
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Test Implementations //
|
||||
//===================== //
|
||||
//////////////////////////
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::serialization::AssertZeroized;
|
||||
|
||||
#[cfg(test)]
|
||||
impl AssertZeroized for VerifyingKey {
|
||||
fn assert_zeroized(&self) {
|
||||
use curve25519_dalek::traits::Identity;
|
||||
|
||||
let Self { point, compressed } = self;
|
||||
|
||||
assert_eq!(point, &EdwardsPoint::identity());
|
||||
assert_eq!(compressed, &EdwardsPoint::identity().compress());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl AssertZeroized for SigningKey {
|
||||
fn assert_zeroized(&self) {
|
||||
let Self {
|
||||
sk,
|
||||
verifying_key,
|
||||
scalar,
|
||||
hash_prefix,
|
||||
} = self;
|
||||
|
||||
verifying_key.assert_zeroized();
|
||||
|
||||
for byte in sk.iter().chain(scalar.to_bytes().iter()).chain(hash_prefix) {
|
||||
assert_eq!(byte, &0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::iter;
|
||||
@@ -497,7 +459,7 @@ mod test {
|
||||
let verifying_key = VerifyingKey::from(&signing_key);
|
||||
verifying_key.verify(&message, &signature).unwrap();
|
||||
|
||||
let custom_pk = Ed25519::public_key(custom_sk);
|
||||
let custom_pk = Ed25519::public_key(&custom_sk);
|
||||
verify(
|
||||
&custom_pk,
|
||||
false,
|
||||
@@ -533,7 +495,7 @@ mod test {
|
||||
.verify_prehashed(message, None, &signature)
|
||||
.unwrap();
|
||||
|
||||
let custom_pk = Ed25519::public_key(custom_sk);
|
||||
let custom_pk = Ed25519::public_key(&custom_sk);
|
||||
verify(
|
||||
&custom_pk,
|
||||
true,
|
||||
|
||||
@@ -15,13 +15,11 @@ use elliptic_curve::group::GroupEncoding;
|
||||
use elliptic_curve::ops::MulByGenerator;
|
||||
use elliptic_curve::sec1::{ModulusSize, ToEncodedPoint};
|
||||
use elliptic_curve::{
|
||||
CurveArithmetic, FieldBytesSize, Group as _, NonZeroScalar, ProjectivePoint, Scalar, SecretKey,
|
||||
point,
|
||||
CurveArithmetic, FieldBytesSize, NonZeroScalar, ProjectivePoint, Scalar, SecretKey, point,
|
||||
};
|
||||
use generic_array::GenericArray;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use voprf::Mode;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use super::{Group, STR_OPAQUE_DERIVE_AUTH_KEY_PAIR};
|
||||
use crate::errors::{InternalError, ProtocolError};
|
||||
@@ -36,15 +34,18 @@ where
|
||||
Repr = GenericArray<u8, <FieldBytesSize<Self> as ModulusSize>::CompressedPointSize>,
|
||||
> + ToEncodedPoint<Self>,
|
||||
{
|
||||
// We don't use `elliptic_curve::PublicKey` because it stores its internals in a
|
||||
// format ideal for serialization and not computation. This is inconsistent with
|
||||
// our other implementations.
|
||||
type Pk = NonIdentity<Self>;
|
||||
|
||||
type PkLen = <FieldBytesSize<Self> as ModulusSize>::CompressedPointSize;
|
||||
|
||||
type Sk = NonZeroScalar<Self>;
|
||||
type Sk = SecretKey<Self>;
|
||||
|
||||
type SkLen = FieldBytesSize<Self>;
|
||||
|
||||
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
GenericArray::clone_from_slice(pk.0.to_encoded_point(true).as_bytes())
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ where
|
||||
}
|
||||
|
||||
fn random_sk<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Sk {
|
||||
SecretKey::<Self>::random(rng).to_nonzero_scalar()
|
||||
SecretKey::<Self>::random(rng)
|
||||
}
|
||||
|
||||
fn derive_scalar(seed: GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError> {
|
||||
@@ -64,29 +65,31 @@ where
|
||||
.map(|scalar| {
|
||||
NonZeroScalar::new(scalar).expect("`voprf::derive_key()` returned a zero scalar")
|
||||
})
|
||||
.map(SecretKey::from)
|
||||
.map_err(InternalError::from)
|
||||
}
|
||||
|
||||
fn public_key(sk: Self::Sk) -> Self::Pk {
|
||||
fn public_key(sk: &Self::Sk) -> Self::Pk {
|
||||
// Non-panicking version in https://github.com/RustCrypto/traits/pull/1833.
|
||||
NonIdentity(
|
||||
point::NonIdentity::new(ProjectivePoint::<Self>::mul_by_generator(&*sk))
|
||||
.expect("multiplying with a non-zero scalar can never yield the identity element"),
|
||||
point::NonIdentity::new(ProjectivePoint::<Self>::mul_by_generator(
|
||||
&sk.to_nonzero_scalar(),
|
||||
))
|
||||
.expect("multiplying with a non-zero scalar can never yield the identity element"),
|
||||
)
|
||||
}
|
||||
|
||||
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
sk.into()
|
||||
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
sk.to_bytes()
|
||||
}
|
||||
|
||||
fn deserialize_take_sk(bytes: &mut &[u8]) -> Result<Self::Sk, ProtocolError> {
|
||||
SecretKey::<Self>::from_bytes(&bytes.take_array("secret key")?)
|
||||
.map(|secret_key| secret_key.to_nonzero_scalar())
|
||||
.map_err(|_| ProtocolError::SerializationError)
|
||||
}
|
||||
}
|
||||
|
||||
impl<G> DiffieHellman<G> for NonZeroScalar<G>
|
||||
impl<G> DiffieHellman<G> for SecretKey<G>
|
||||
where
|
||||
G: CurveArithmetic + voprf::CipherSuite<Group = G> + voprf::Group<Scalar = Scalar<G>>,
|
||||
FieldBytesSize<G>: ModulusSize,
|
||||
@@ -95,15 +98,19 @@ where
|
||||
> + ToEncodedPoint<G>,
|
||||
{
|
||||
fn diffie_hellman(
|
||||
self,
|
||||
pk: NonIdentity<G>,
|
||||
&self,
|
||||
pk: &NonIdentity<G>,
|
||||
) -> GenericArray<u8, <FieldBytesSize<G> as ModulusSize>::CompressedPointSize> {
|
||||
GenericArray::clone_from_slice((pk.0 * self).to_encoded_point(true).as_bytes())
|
||||
GenericArray::clone_from_slice(
|
||||
(pk.0 * self.to_nonzero_scalar())
|
||||
.to_encoded_point(true)
|
||||
.as_bytes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper around [`NonIdentity`](point::NonIdentity) to implement [`Zeroize`].
|
||||
// TODO: remove after https://github.com/RustCrypto/traits/pull/1832.
|
||||
/// Wrapper around [`NonIdentity`](point::NonIdentity) to [`Eq`].
|
||||
// TODO: remove after https://github.com/RustCrypto/traits/pull/1834.
|
||||
#[derive_where(Clone, Copy)]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
@@ -133,33 +140,3 @@ impl<G: CurveArithmetic> PartialEq for NonIdentity<G> {
|
||||
}
|
||||
|
||||
impl<G: CurveArithmetic> Eq for NonIdentity<G> {}
|
||||
|
||||
impl<G: CurveArithmetic> Zeroize for NonIdentity<G> {
|
||||
fn zeroize(&mut self) {
|
||||
self.0 = point::NonIdentity::new(ProjectivePoint::<G>::generator()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Test Implementations //
|
||||
//===================== //
|
||||
//////////////////////////
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::serialization::AssertZeroized;
|
||||
|
||||
#[cfg(test)]
|
||||
impl<G: CurveArithmetic> AssertZeroized for NonIdentity<G> {
|
||||
fn assert_zeroized(&self) {
|
||||
assert_eq!(self.0.to_point(), ProjectivePoint::<G>::generator());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl<G: CurveArithmetic> AssertZeroized for NonZeroScalar<G> {
|
||||
fn assert_zeroized(&self) {
|
||||
use elliptic_curve::Field;
|
||||
|
||||
assert_eq!(**self, Scalar::<G>::ONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ pub mod ristretto255;
|
||||
|
||||
use generic_array::{ArrayLength, GenericArray};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use zeroize::Zeroize;
|
||||
use zeroize::ZeroizeOnDrop;
|
||||
|
||||
use crate::errors::{InternalError, ProtocolError};
|
||||
|
||||
@@ -27,16 +27,16 @@ const STR_OPAQUE_DERIVE_AUTH_KEY_PAIR: [u8; 33] = *b"OPAQUE-DeriveDiffieHellmanK
|
||||
/// A group representation for use in the key exchange
|
||||
pub trait Group {
|
||||
/// Public key
|
||||
type Pk: Copy + Zeroize;
|
||||
type Pk: Clone;
|
||||
/// Length of the public key
|
||||
type PkLen: ArrayLength<u8>;
|
||||
/// Secret key
|
||||
type Sk: Copy + Zeroize;
|
||||
type Sk: Clone + ZeroizeOnDrop;
|
||||
/// Length of the secret key
|
||||
type SkLen: ArrayLength<u8>;
|
||||
|
||||
/// Serializes `self`
|
||||
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen>;
|
||||
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen>;
|
||||
|
||||
/// Return a public key from its fixed-length bytes representation
|
||||
///
|
||||
@@ -50,10 +50,10 @@ pub trait Group {
|
||||
fn derive_scalar(seed: GenericArray<u8, Self::SkLen>) -> Result<Self::Sk, InternalError>;
|
||||
|
||||
/// Return a public key from its secret key
|
||||
fn public_key(sk: Self::Sk) -> Self::Pk;
|
||||
fn public_key(sk: &Self::Sk) -> Self::Pk;
|
||||
|
||||
/// Serializes `self`
|
||||
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen>;
|
||||
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen>;
|
||||
|
||||
/// Return a public key from its fixed-length bytes representation
|
||||
///
|
||||
|
||||
@@ -19,7 +19,7 @@ use generic_array::GenericArray;
|
||||
use generic_array::typenum::{IsLess, IsLessOrEqual, U32, U256};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use voprf::Mode;
|
||||
use zeroize::Zeroize;
|
||||
use zeroize::ZeroizeOnDrop;
|
||||
|
||||
use super::{Group, STR_OPAQUE_DERIVE_AUTH_KEY_PAIR};
|
||||
use crate::errors::{InternalError, ProtocolError};
|
||||
@@ -37,7 +37,7 @@ impl Group for Ristretto255 {
|
||||
type Sk = NonZeroScalar;
|
||||
type SkLen = U32;
|
||||
|
||||
fn serialize_pk(pk: Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
fn serialize_pk(pk: &Self::Pk) -> GenericArray<u8, Self::PkLen> {
|
||||
pk.0.compress().to_bytes().into()
|
||||
}
|
||||
|
||||
@@ -64,11 +64,11 @@ impl Group for Ristretto255 {
|
||||
.map_err(InternalError::from)
|
||||
}
|
||||
|
||||
fn public_key(sk: Self::Sk) -> Self::Pk {
|
||||
fn public_key(sk: &Self::Sk) -> Self::Pk {
|
||||
NonIdentity(RISTRETTO_BASEPOINT_POINT * sk.0)
|
||||
}
|
||||
|
||||
fn serialize_sk(sk: Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
fn serialize_sk(sk: &Self::Sk) -> GenericArray<u8, Self::SkLen> {
|
||||
sk.0.to_bytes().into()
|
||||
}
|
||||
|
||||
@@ -81,14 +81,14 @@ impl Group for Ristretto255 {
|
||||
}
|
||||
|
||||
impl DiffieHellman<Ristretto255> for NonZeroScalar {
|
||||
fn diffie_hellman(self, pk: NonIdentity) -> GenericArray<u8, U32> {
|
||||
Ristretto255::serialize_pk(NonIdentity(pk.0 * self.0))
|
||||
fn diffie_hellman(&self, pk: &NonIdentity) -> GenericArray<u8, U32> {
|
||||
Ristretto255::serialize_pk(&NonIdentity(pk.0 * self.0))
|
||||
}
|
||||
}
|
||||
|
||||
/// Non-identity point wrapper for [`RistrettoPoint`].
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Zeroize)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct NonIdentity(
|
||||
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_pk"))] RistrettoPoint,
|
||||
);
|
||||
@@ -119,7 +119,7 @@ where
|
||||
|
||||
/// Non-zero scalar wrapper for [`Scalar`]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Zeroize)]
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, ZeroizeOnDrop)]
|
||||
pub struct NonZeroScalar(
|
||||
#[cfg_attr(feature = "serde", serde(deserialize_with = "serde_deserialize_sk"))] Scalar,
|
||||
);
|
||||
@@ -223,25 +223,3 @@ impl voprf::Group for Ristretto255 {
|
||||
<voprf::Ristretto255 as voprf::Group>::deserialize_scalar(scalar_bits)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Test Implementations //
|
||||
//===================== //
|
||||
//////////////////////////
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::serialization::AssertZeroized;
|
||||
|
||||
#[cfg(test)]
|
||||
impl AssertZeroized for NonIdentity {
|
||||
fn assert_zeroized(&self) {
|
||||
assert_eq!(self.0, RistrettoPoint::default());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl AssertZeroized for NonZeroScalar {
|
||||
fn assert_zeroized(&self) {
|
||||
assert_eq!(self.0, Scalar::default());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user