Skip to content

Commit

Permalink
Implement partial equality for key types (#102)
Browse files Browse the repository at this point in the history
* Implement parital equality for key types

Signed-off-by: Justin Abrahms <[email protected]>

* use subtle for PartialEq impl for SigningKey

* fix no_std

---------

Signed-off-by: Justin Abrahms <[email protected]>
Co-authored-by: Justin Abrahms <[email protected]>
  • Loading branch information
conradoplg and justinabrahms authored Nov 27, 2023
1 parent ff74928 commit eae0120
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 16 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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"
Expand Down
15 changes: 15 additions & 0 deletions src/signing_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/verification_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down
25 changes: 11 additions & 14 deletions tests/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit eae0120

Please sign in to comment.