Implement partial equality for key types (#102)

* Implement parital equality for key types

Signed-off-by: Justin Abrahms <justin@abrah.ms>

* use subtle for PartialEq impl for SigningKey

* fix no_std

---------

Signed-off-by: Justin Abrahms <justin@abrah.ms>
Co-authored-by: Justin Abrahms <justin@abrah.ms>
This commit is contained in:
Conrado Gouvea 2023-11-27 11:40:06 -03:00 committed by GitHub
parent ff74928aae
commit eae0120f98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 16 deletions

View File

@ -2,6 +2,10 @@
Entries are listed in reverse chronological order.
# 4.0.4 (Unreleased)
* Implement `PartialEq` and `Eq` in `SigningKey` and `VerificationKey`.
# 4.0.3
* Update `curve25519-dalek` to `4.1.0`

View File

@ -27,6 +27,7 @@ pkcs8 = { version = "0.10.1", optional = true, features = ["alloc", "pem"] }
rand_core = "0.6"
serde = { version = "1", default-features = false, optional = true, features = ["derive"] }
sha2 = { version = "0.10", default-features = false }
subtle = { version = "2.5.0", default-features = false }
zeroize = { version = "1.5", features = [ "zeroize_derive" ] }
[dev-dependencies]
@ -43,7 +44,7 @@ default = ["serde", "std"]
pem = ["der", "ed25519/pem"]
pkcs8 = ["dep:pkcs8"]
serde = ["dep:serde", "ed25519/serde"]
std = ["ed25519/std"]
std = ["ed25519/std", "subtle/std"]
[[test]]
name = "rfc8032"

View File

@ -13,6 +13,7 @@ use core::convert::TryInto;
use curve25519_dalek::{constants, digest::Update, scalar::Scalar};
use rand_core::{CryptoRng, RngCore};
use sha2::{Digest, Sha512};
use subtle::ConstantTimeEq;
use zeroize::Zeroize;
pub use ed25519::{
@ -137,6 +138,20 @@ impl From<[u8; 32]> for SigningKey {
}
}
impl ConstantTimeEq for SigningKey {
fn ct_eq(&self, other: &Self) -> subtle::Choice {
self.seed.ct_eq(&other.seed)
}
}
impl PartialEq for SigningKey {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(other).into()
}
}
impl Eq for SigningKey {}
#[cfg(feature = "pkcs8")]
impl<'a> TryFrom<PrivateKeyInfo<'a>> for SigningKey {
type Error = Error;

View File

@ -113,7 +113,7 @@ impl<'a> TryFrom<SubjectPublicKeyInfoRef<'a>> for VerificationKeyBytes {
/// Curve25519, and non-canonical encodings MUST be accepted;
///
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#concreteed25519
#[derive(Copy, Clone, Debug)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(try_from = "VerificationKeyBytes"))]
#[cfg_attr(feature = "serde", serde(into = "VerificationKeyBytes"))]

View File

@ -11,31 +11,28 @@ fn parsing() {
let pkb = VerificationKeyBytes::from(&sk);
let sig = sk.sign(b"test");
// Most of these types don't implement Eq, so we check a round trip
// conversion to bytes, using these as the reference points:
let sk_array: [u8; 32] = sk.into();
let pk_array: [u8; 32] = pk.into();
let pkb_array: [u8; 32] = pkb.into();
let sig_array: [u8; 64] = sig.into();
let sk2 = SigningKey::try_from(sk.as_ref()).unwrap();
let pk2 = VerificationKey::try_from(pk.as_ref()).unwrap();
let pkb2 = VerificationKeyBytes::try_from(pkb.as_ref()).unwrap();
let sig2 = Signature::try_from(<[u8; 64]>::from(sig).as_ref()).unwrap();
let sk2 = SigningKey::try_from(sk_array).unwrap();
let pk2 = VerificationKey::try_from(pk_array).unwrap();
let pkb2 = VerificationKeyBytes::try_from(pkb_array).unwrap();
let sig2 = Signature::try_from(sig_array).unwrap();
assert_eq!(&sk_array[..], sk2.as_ref());
assert_eq!(&pk_array[..], pk2.as_ref());
assert_eq!(&pkb_array[..], pkb2.as_ref());
assert_eq!(&sig_array[..], <[u8; 64]>::from(sig2).as_ref());
assert_eq!(sk, sk2);
assert_eq!(pk, pk2);
assert_eq!(pkb, pkb2);
assert_eq!(sig, sig2);
let sk3: SigningKey = bincode::deserialize(sk.as_ref()).unwrap();
let pk3: VerificationKey = bincode::deserialize(pk.as_ref()).unwrap();
let pkb3: VerificationKeyBytes = bincode::deserialize(pkb.as_ref()).unwrap();
assert_eq!(&sk_array[..], sk3.as_ref());
assert_eq!(&pk_array[..], pk3.as_ref());
assert_eq!(&pkb_array[..], pkb3.as_ref());
assert_eq!(sk, sk3);
assert_eq!(pk, pk3);
assert_eq!(pkb, pkb3);
}
#[test]