Skip to content

Commit

Permalink
core/identity: Implement Hash and Ord for PublicKey (#2915)
Browse files Browse the repository at this point in the history
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
  • Loading branch information
futpib and thomaseizinger authored Sep 22, 2022
1 parent 0a12418 commit bcff814
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

# 0.49.0 - [unreleased]

- Update to [`libp2p-core` `v0.36.1`](core/CHANGELOG.md#0361).

- Update to [`libp2p-tcp` `v0.37.0`](transports/tcp/CHANGELOG.md#0370).
- Update individual crates.
- Update to [`libp2p-ping` `v0.39.1`](protocols/ping/CHANGELOG.md#0391).
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ instant = "0.1.11" # Explicit dependency to be used in `wasm-bindgen` feature
lazy_static = "1.2"

libp2p-autonat = { version = "0.7.0", path = "protocols/autonat", optional = true }
libp2p-core = { version = "0.36.0", path = "core", default-features = false }
libp2p-core = { version = "0.36.1", path = "core", default-features = false }
libp2p-dcutr = { version = "0.6.0", path = "protocols/dcutr", optional = true }
libp2p-floodsub = { version = "0.39.1", path = "protocols/floodsub", optional = true }
libp2p-identify = { version = "0.39.0", path = "protocols/identify", optional = true }
Expand Down
6 changes: 6 additions & 0 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# 0.36.1 - [unreleased]

- Implement `Hash` and `Ord` for `PublicKey`. See [PR 2915].

[PR 2915]: https://github.com/libp2p/rust-libp2p/pull/2915

# 0.36.0

- Make RSA keypair support optional. To enable RSA support, `rsa` feature should be enabled.
Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "libp2p-core"
edition = "2021"
rust-version = "1.56.1"
description = "Core traits and structs of libp2p"
version = "0.36.0"
version = "0.36.1"
authors = ["Parity Technologies <admin@parity.io>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand Down
20 changes: 19 additions & 1 deletion core/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl zeroize::Zeroize for keys_proto::PrivateKey {
}

/// The public key of a node's identity keypair.
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum PublicKey {
/// A public Ed25519 key.
Ed25519(ed25519::PublicKey),
Expand Down Expand Up @@ -379,4 +379,22 @@ mod tests {

assert_eq!(expected_peer_id, peer_id);
}

#[test]
fn public_key_implements_hash() {
use std::hash::Hash;

fn assert_implements_hash<T: Hash>() {}

assert_implements_hash::<PublicKey>();
}

#[test]
fn public_key_implements_ord() {
use std::cmp::Ord;

fn assert_implements_ord<T: Ord>() {}

assert_implements_ord::<PublicKey>();
}
}
16 changes: 15 additions & 1 deletion core/src/identity/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
//! ECDSA keys with secp256r1 curve support.

use super::error::DecodingError;
use core::cmp;
use core::fmt;
use core::hash;
use p256::{
ecdsa::{
signature::{Signer, Verifier},
Expand Down Expand Up @@ -117,7 +119,7 @@ impl fmt::Debug for SecretKey {
}

/// An ECDSA public key.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, Eq, PartialOrd, Ord)]
pub struct PublicKey(VerifyingKey);

impl PublicKey {
Expand Down Expand Up @@ -222,6 +224,18 @@ impl fmt::Debug for PublicKey {
}
}

impl cmp::PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.to_bytes().eq(&other.to_bytes())
}
}

impl hash::Hash for PublicKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.to_bytes().hash(state);
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
28 changes: 27 additions & 1 deletion core/src/identity/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
//! Ed25519 keys.

use super::error::DecodingError;
use core::cmp;
use core::fmt;
use core::hash;
use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
use rand::RngCore;
use std::convert::TryFrom;
Expand Down Expand Up @@ -113,7 +115,7 @@ impl From<SecretKey> for Keypair {
}

/// An Ed25519 public key.
#[derive(PartialEq, Eq, Clone)]
#[derive(Eq, Clone)]
pub struct PublicKey(ed25519::PublicKey);

impl fmt::Debug for PublicKey {
Expand All @@ -126,6 +128,30 @@ impl fmt::Debug for PublicKey {
}
}

impl cmp::PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.0.as_bytes().eq(other.0.as_bytes())
}
}

impl hash::Hash for PublicKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.0.as_bytes().hash(state);
}
}

impl cmp::PartialOrd for PublicKey {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.0.as_bytes().partial_cmp(other.0.as_bytes())
}
}

impl cmp::Ord for PublicKey {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.0.as_bytes().cmp(other.0.as_bytes())
}
}

impl PublicKey {
/// Verify the Ed25519 signature on a message using the public key.
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
Expand Down
11 changes: 2 additions & 9 deletions core/src/identity/rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl Keypair {
}

/// An RSA public key.
#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct PublicKey(Vec<u8>);

impl PublicKey {
Expand Down Expand Up @@ -306,21 +306,14 @@ impl DerDecodable<'_> for Asn1SubjectPublicKeyInfo {
mod tests {
use super::*;
use quickcheck::*;
use std::fmt;

const KEY1: &'static [u8] = include_bytes!("test/rsa-2048.pk8");
const KEY2: &'static [u8] = include_bytes!("test/rsa-3072.pk8");
const KEY3: &'static [u8] = include_bytes!("test/rsa-4096.pk8");

#[derive(Clone)]
#[derive(Clone, Debug)]
struct SomeKeypair(Keypair);

impl fmt::Debug for SomeKeypair {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SomeKeypair")
}
}

impl Arbitrary for SomeKeypair {
fn arbitrary(g: &mut Gen) -> SomeKeypair {
let mut key = g.choose(&[KEY1, KEY2, KEY3]).unwrap().to_vec();
Expand Down
28 changes: 27 additions & 1 deletion core/src/identity/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

use super::error::{DecodingError, SigningError};
use asn1_der::typed::{DerDecodable, Sequence};
use core::cmp;
use core::fmt;
use core::hash;
use libsecp256k1::{Message, Signature};
use sha2::{Digest as ShaDigestTrait, Sha256};
use zeroize::Zeroize;
Expand Down Expand Up @@ -150,7 +152,7 @@ impl SecretKey {
}

/// A Secp256k1 public key.
#[derive(PartialEq, Eq, Clone)]
#[derive(Eq, Clone)]
pub struct PublicKey(libsecp256k1::PublicKey);

impl fmt::Debug for PublicKey {
Expand All @@ -163,6 +165,30 @@ impl fmt::Debug for PublicKey {
}
}

impl cmp::PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.encode().eq(&other.encode())
}
}

impl hash::Hash for PublicKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.encode().hash(state);
}
}

impl cmp::PartialOrd for PublicKey {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.encode().partial_cmp(&other.encode())
}
}

impl cmp::Ord for PublicKey {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.encode().cmp(&other.encode())
}
}

impl PublicKey {
/// Verify the Secp256k1 signature on a message using the public key.
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
Expand Down

0 comments on commit bcff814

Please sign in to comment.