From 7d5e6068681c35c925af4681255ec835a7f306ae Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Mon, 13 Mar 2023 19:06:40 +0800 Subject: [PATCH 01/26] feat: make mdns::Event clone-able --- protocols/mdns/src/behaviour.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index b34a1a73629..f2709e90bdf 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -339,7 +339,7 @@ where } /// Event that can be produced by the `Mdns` behaviour. -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Event { /// Discovered nodes through mDNS. Discovered(DiscoveredAddrsIter), @@ -352,6 +352,7 @@ pub enum Event { } /// Iterator that produces the list of addresses that have been discovered. +#[derive(Clone)] pub struct DiscoveredAddrsIter { inner: smallvec::IntoIter<[(PeerId, Multiaddr); 4]>, } @@ -379,6 +380,7 @@ impl fmt::Debug for DiscoveredAddrsIter { } /// Iterator that produces the list of addresses that have expired. +#[derive(Clone)] pub struct ExpiredAddrsIter { inner: smallvec::IntoIter<[(PeerId, Multiaddr); 4]>, } From a72e5e2f1edf92324268b837a63fd5b9f00e5373 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Mon, 13 Mar 2023 20:23:28 +0800 Subject: [PATCH 02/26] docs: filling CHANGELOG for PR 3606 Unreleased patch version 0.43.1 bumped. Added entry for PR 3606: Deriving 'Clone' for 'mdns::Event' --- protocols/mdns/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/protocols/mdns/CHANGELOG.md b/protocols/mdns/CHANGELOG.md index c2b548e3389..62a361a0608 100644 --- a/protocols/mdns/CHANGELOG.md +++ b/protocols/mdns/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.43.1 [unreleased] + +- Deriving `Clone` for `mdns::Event`. See [PR 3606]. + # 0.43.0 - Update to `libp2p-core` `v0.39.0`. From 926c7ca99cd5c2de45d6610da45a41ab418ebe3b Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 14 Mar 2023 03:17:21 +1100 Subject: [PATCH 03/26] Update protocols/mdns/CHANGELOG.md --- protocols/mdns/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/mdns/CHANGELOG.md b/protocols/mdns/CHANGELOG.md index 62a361a0608..c877ca48ccb 100644 --- a/protocols/mdns/CHANGELOG.md +++ b/protocols/mdns/CHANGELOG.md @@ -2,6 +2,7 @@ - Deriving `Clone` for `mdns::Event`. See [PR 3606]. +[PR 3606]: https://github.com/libp2p/rust-libp2p/pull/3606 # 0.43.0 - Update to `libp2p-core` `v0.39.0`. From 49d26c4795a45471fc67af3e6bca6477faf86244 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 14 Mar 2023 03:17:36 +1100 Subject: [PATCH 04/26] Update protocols/mdns/CHANGELOG.md --- protocols/mdns/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/mdns/CHANGELOG.md b/protocols/mdns/CHANGELOG.md index c877ca48ccb..0c3b88c018c 100644 --- a/protocols/mdns/CHANGELOG.md +++ b/protocols/mdns/CHANGELOG.md @@ -1,6 +1,6 @@ # 0.43.1 [unreleased] -- Deriving `Clone` for `mdns::Event`. See [PR 3606]. +- Derive `Clone` for `mdns::Event`. See [PR 3606]. [PR 3606]: https://github.com/libp2p/rust-libp2p/pull/3606 # 0.43.0 From a8ff1eb46a336807fb06805a88ccbbde335591f3 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Thu, 16 Mar 2023 10:46:39 +0800 Subject: [PATCH 05/26] feat: change 'mdns::Event' to hold 'SmallVec' --- protocols/mdns/src/behaviour.rs | 68 ++------------------------------- 1 file changed, 4 insertions(+), 64 deletions(-) diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index f2709e90bdf..6f590c49882 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -304,9 +304,7 @@ where } } if !discovered.is_empty() { - let event = Event::Discovered(DiscoveredAddrsIter { - inner: discovered.into_iter(), - }); + let event = Event::Discovered(discovered); return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); } // Emit expired event. @@ -323,9 +321,7 @@ where true }); if !expired.is_empty() { - let event = Event::Expired(ExpiredAddrsIter { - inner: expired.into_iter(), - }); + let event = Event::Expired(expired); return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); } if let Some(closest_expiration) = closest_expiration { @@ -342,67 +338,11 @@ where #[derive(Debug, Clone)] pub enum Event { /// Discovered nodes through mDNS. - Discovered(DiscoveredAddrsIter), + Discovered(SmallVec<[(PeerId, Multiaddr); 4]>), /// The given combinations of `PeerId` and `Multiaddr` have expired. /// /// Each discovered record has a time-to-live. When this TTL expires and the address hasn't /// been refreshed, we remove it from the list and emit it as an `Expired` event. - Expired(ExpiredAddrsIter), -} - -/// Iterator that produces the list of addresses that have been discovered. -#[derive(Clone)] -pub struct DiscoveredAddrsIter { - inner: smallvec::IntoIter<[(PeerId, Multiaddr); 4]>, -} - -impl Iterator for DiscoveredAddrsIter { - type Item = (PeerId, Multiaddr); - - #[inline] - fn next(&mut self) -> Option { - self.inner.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} - -impl ExactSizeIterator for DiscoveredAddrsIter {} - -impl fmt::Debug for DiscoveredAddrsIter { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("DiscoveredAddrsIter").finish() - } -} - -/// Iterator that produces the list of addresses that have expired. -#[derive(Clone)] -pub struct ExpiredAddrsIter { - inner: smallvec::IntoIter<[(PeerId, Multiaddr); 4]>, -} - -impl Iterator for ExpiredAddrsIter { - type Item = (PeerId, Multiaddr); - - #[inline] - fn next(&mut self) -> Option { - self.inner.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } -} - -impl ExactSizeIterator for ExpiredAddrsIter {} - -impl fmt::Debug for ExpiredAddrsIter { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("ExpiredAddrsIter").finish() - } + Expired(SmallVec<[(PeerId, Multiaddr); 4]>), } From 4cec5fac84941c95cb50a35a3dc7395e2f71bf3c Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Thu, 16 Mar 2023 10:48:05 +0800 Subject: [PATCH 06/26] test: adapting test to 'mdns::Event' change --- protocols/mdns/tests/use-async-std.rs | 20 ++++++++++---------- protocols/mdns/tests/use-tokio.rs | 16 ++++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/protocols/mdns/tests/use-async-std.rs b/protocols/mdns/tests/use-async-std.rs index 139fcca1d50..bfc3cd1201d 100644 --- a/protocols/mdns/tests/use-async-std.rs +++ b/protocols/mdns/tests/use-async-std.rs @@ -61,13 +61,13 @@ async fn test_expired_async_std() { loop { match futures::future::select(a.next_behaviour_event(), b.next_behaviour_event()).await { - Either::Left((Event::Expired(mut peers), _)) => { - if peers.any(|(p, _)| p == b_peer_id) { + Either::Left((Event::Expired(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == b_peer_id) { return; } } - Either::Right((Event::Expired(mut peers), _)) => { - if peers.any(|(p, _)| p == a_peer_id) { + Either::Right((Event::Expired(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == a_peer_id) { return; } } @@ -93,8 +93,8 @@ async fn test_no_expiration_on_close_async_std() { // 1. Connect via address from mDNS event loop { - if let Event::Discovered(mut peers) = a.next_behaviour_event().await { - if let Some((_, addr)) = peers.find(|(p, _)| p == &b_peer_id) { + if let Event::Discovered(peers) = a.next_behaviour_event().await { + if let Some((_, addr)) = peers.into_iter().find(|(p, _)| p == &b_peer_id) { a.dial_and_wait(addr).await; break; } @@ -130,13 +130,13 @@ async fn run_discovery_test(config: Config) { while !discovered_a && !discovered_b { match futures::future::select(a.next_behaviour_event(), b.next_behaviour_event()).await { - Either::Left((Event::Discovered(mut peers), _)) => { - if peers.any(|(p, _)| p == b_peer_id) { + Either::Left((Event::Discovered(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == b_peer_id) { discovered_b = true; } } - Either::Right((Event::Discovered(mut peers), _)) => { - if peers.any(|(p, _)| p == a_peer_id) { + Either::Right((Event::Discovered(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == a_peer_id) { discovered_a = true; } } diff --git a/protocols/mdns/tests/use-tokio.rs b/protocols/mdns/tests/use-tokio.rs index e18ae28fee7..229418437f4 100644 --- a/protocols/mdns/tests/use-tokio.rs +++ b/protocols/mdns/tests/use-tokio.rs @@ -59,13 +59,13 @@ async fn test_expired_tokio() { loop { match futures::future::select(a.next_behaviour_event(), b.next_behaviour_event()).await { - Either::Left((Event::Expired(mut peers), _)) => { - if peers.any(|(p, _)| p == b_peer_id) { + Either::Left((Event::Expired(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == b_peer_id) { return; } } - Either::Right((Event::Expired(mut peers), _)) => { - if peers.any(|(p, _)| p == a_peer_id) { + Either::Right((Event::Expired(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == a_peer_id) { return; } } @@ -86,13 +86,13 @@ async fn run_discovery_test(config: Config) { while !discovered_a && !discovered_b { match futures::future::select(a.next_behaviour_event(), b.next_behaviour_event()).await { - Either::Left((Event::Discovered(mut peers), _)) => { - if peers.any(|(p, _)| p == b_peer_id) { + Either::Left((Event::Discovered(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == b_peer_id) { discovered_b = true; } } - Either::Right((Event::Discovered(mut peers), _)) => { - if peers.any(|(p, _)| p == a_peer_id) { + Either::Right((Event::Discovered(peers), _)) => { + if peers.into_iter().any(|(p, _)| p == a_peer_id) { discovered_a = true; } } From 18811d24ae748ca703f51ef66bdcb3961402965c Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Thu, 16 Mar 2023 17:30:41 +0800 Subject: [PATCH 07/26] feat(mdns): change 'mdns::Event' to hold 'Vec' --- protocols/mdns/src/behaviour.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index 6f590c49882..f175a94aa06 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -285,7 +285,7 @@ where } } // Emit discovered event. - let mut discovered = SmallVec::<[(PeerId, Multiaddr); 4]>::new(); + let mut discovered = Vec::new(); for iface_state in self.iface_states.values_mut() { while let Poll::Ready((peer, addr, expiration)) = iface_state.poll(cx, &self.listen_addresses) @@ -310,7 +310,7 @@ where // Emit expired event. let now = Instant::now(); let mut closest_expiration = None; - let mut expired = SmallVec::<[(PeerId, Multiaddr); 4]>::new(); + let mut expired = Vec::new(); self.discovered_nodes.retain(|(peer, addr, expiration)| { if *expiration <= now { log::info!("expired: {} {}", peer, addr); @@ -338,11 +338,11 @@ where #[derive(Debug, Clone)] pub enum Event { /// Discovered nodes through mDNS. - Discovered(SmallVec<[(PeerId, Multiaddr); 4]>), + Discovered(Vec<(PeerId, Multiaddr)>), /// The given combinations of `PeerId` and `Multiaddr` have expired. /// /// Each discovered record has a time-to-live. When this TTL expires and the address hasn't /// been refreshed, we remove it from the list and emit it as an `Expired` event. - Expired(SmallVec<[(PeerId, Multiaddr); 4]>), + Expired(Vec<(PeerId, Multiaddr)>), } From abdce7ecbb16256bcad5118fd0d05ce644f01d5f Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Thu, 16 Mar 2023 17:39:50 +0800 Subject: [PATCH 08/26] doc: add entry for #3621 New unreleased minor version 0.44.0. --- protocols/mdns/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/protocols/mdns/CHANGELOG.md b/protocols/mdns/CHANGELOG.md index 0c3b88c018c..6225dc376e5 100644 --- a/protocols/mdns/CHANGELOG.md +++ b/protocols/mdns/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.44.0 [unreleased] + +- Change `mdns::Event` to hold `Vec`. See [PR 3621] + +[PR 3621]: https://github.com/libp2p/rust-libp2p/pull/3621 + # 0.43.1 [unreleased] - Derive `Clone` for `mdns::Event`. See [PR 3606]. From d5c246cc265e703d4f8af76f8c1de370a3f8c821 Mon Sep 17 00:00:00 2001 From: DrHuangMHT Date: Thu, 16 Mar 2023 22:05:01 +0800 Subject: [PATCH 09/26] Update protocols/mdns/CHANGELOG.md Co-authored-by: Thomas Eizinger --- protocols/mdns/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocols/mdns/CHANGELOG.md b/protocols/mdns/CHANGELOG.md index 6225dc376e5..04a8162e065 100644 --- a/protocols/mdns/CHANGELOG.md +++ b/protocols/mdns/CHANGELOG.md @@ -1,6 +1,7 @@ # 0.44.0 [unreleased] -- Change `mdns::Event` to hold `Vec`. See [PR 3621] +- Change `mdns::Event` to hold `Vec` and remove `DiscoveredAddrsIter` and `ExpiredAddrsIter`. + See [PR 3621]. [PR 3621]: https://github.com/libp2p/rust-libp2p/pull/3621 From 9d45cf3d8c91221333f91bee67b675e0b043c623 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Sun, 26 Mar 2023 19:36:50 +0800 Subject: [PATCH 10/26] Remove conflict marker to resolve conflicts --- protocols/mdns/src/behaviour.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index 56b9f9af144..5186ce91cb7 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -304,15 +304,8 @@ where } } if !discovered.is_empty() { -<<<<<<< HEAD let event = Event::Discovered(discovered); - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); -======= - let event = Event::Discovered(DiscoveredAddrsIter { - inner: discovered.into_iter(), - }); return Poll::Ready(ToSwarm::GenerateEvent(event)); ->>>>>>> upstream/master } // Emit expired event. let now = Instant::now(); @@ -328,15 +321,8 @@ where true }); if !expired.is_empty() { -<<<<<<< HEAD let event = Event::Expired(expired); - return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)); -======= - let event = Event::Expired(ExpiredAddrsIter { - inner: expired.into_iter(), - }); return Poll::Ready(ToSwarm::GenerateEvent(event)); ->>>>>>> upstream/master } if let Some(closest_expiration) = closest_expiration { let mut timer = P::Timer::at(closest_expiration); From 7cf55564c141c7dd41f875b7f288ed4c43c8a169 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 14 Apr 2023 09:07:22 +0200 Subject: [PATCH 11/26] Update protocols/mdns/CHANGELOG.md --- protocols/mdns/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/mdns/CHANGELOG.md b/protocols/mdns/CHANGELOG.md index 10b8743b07d..2bd1d3d247c 100644 --- a/protocols/mdns/CHANGELOG.md +++ b/protocols/mdns/CHANGELOG.md @@ -1,4 +1,4 @@ -# 0.44.0 [unreleased] +# 0.44.0 - unreleased - Change `mdns::Event` to hold `Vec` and remove `DiscoveredAddrsIter` and `ExpiredAddrsIter`. See [PR 3621]. From 7b6c9dc7c48ef9719aa0ff9398b5f71e7c10936c Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Tue, 2 May 2023 20:18:55 +0800 Subject: [PATCH 12/26] implement 'encode_pkcs8_der' for 'ecdsa::SecretKey' --- identity/Cargo.toml | 2 +- identity/src/ecdsa.rs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/identity/Cargo.toml b/identity/Cargo.toml index a69c2c632dd..fa57a8f72e2 100644 --- a/identity/Cargo.toml +++ b/identity/Cargo.toml @@ -19,7 +19,7 @@ libsecp256k1 = { version = "0.7.0", optional = true } log = "0.4" multiaddr = { version = "0.17.1", optional = true } multihash = { version = "0.17.0", default-features = false, features = ["std"], optional = true } -p256 = { version = "0.12", default-features = false, features = ["ecdsa", "std"], optional = true } +p256 = { version = "0.12", default-features = false, features = ["ecdsa", "std", "pem"], optional = true } quick-protobuf = { version = "0.8.1", optional = true } rand = { version = "0.8", optional = true } sec1 = { version = "0.3.0", features = ["std"], optional = true } # Activate `std` feature until https://github.com/RustCrypto/traits/pull/1131 is released. diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index 2210e4d128b..4f6394e3b1b 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -24,6 +24,7 @@ use super::error::DecodingError; use core::cmp; use core::fmt; use core::hash; +use p256::pkcs8::EncodePrivateKey; use p256::{ ecdsa::{ signature::{Signer, Verifier}, @@ -122,6 +123,23 @@ impl SecretKey { .map_err(|err| DecodingError::failed_to_parse("ecdsa p256 secret key", err)) .map(SecretKey) } + + /// Encode the secret key into DER-encoded PKCS#8 format. + pub fn encode_pkcs8_der(&self) -> Vec { + self.0 + .to_pkcs8_der() + .expect("Encoding to pkcs#8 format to succeed") + .to_bytes() + .to_vec() + } + + // Cannot implement this because error type does not implement `std::error::Error` + // pub fn try_decode_pkcs8_der(buf:&[u8])->Result{ + // match SigningKey::from_pkcs8_der(buf){ + // Ok(key) => Ok(SecretKey(key)), + // Err(e) => Err(DecodingError::failed_to_parse("ECDSA", e)), + // } + // } } impl fmt::Debug for SecretKey { From 8ec82631b159b36da6ec5c6986736efdbfc12ff3 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Tue, 2 May 2023 23:24:37 +0800 Subject: [PATCH 13/26] bump 'p256' from 0.12 to 0.13 --- Cargo.lock | 206 ++++++++++++++++++++++++++++++++++-------- identity/Cargo.toml | 2 +- identity/src/ecdsa.rs | 2 +- 3 files changed, 168 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a883c7e6b0d..952114a6a34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,6 +517,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.13.1" @@ -861,9 +867,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" [[package]] name = "core-foundation" @@ -1026,6 +1032,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "crypto-bigint" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1247,7 +1265,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" dependencies = [ "const-oid", - "pem-rfc7468", + "pem-rfc7468 0.6.0", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e58dffcdcc8ee7b22f0c1f71a69243d7c2d9ad87b5a14361f2424a1565c219" +dependencies = [ + "const-oid", + "pem-rfc7468 0.7.0", "zeroize", ] @@ -1326,6 +1355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", + "const-oid", "crypto-common", "subtle", ] @@ -1365,21 +1395,22 @@ version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" dependencies = [ - "der", - "elliptic-curve", - "rfc6979", + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", "signature 1.6.4", ] [[package]] name = "ecdsa" -version = "0.15.1" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12844141594ad74185a926d030f3b605f6a903b4e3fec351f3ea338ac5b7637e" +checksum = "a48e5d537b8a30c0b023116d981b16334be1485af7ca68db3a2b7024cbc957fd" dependencies = [ - "der", - "elliptic-curve", - "rfc6979", + "der 0.7.5", + "digest 0.10.6", + "elliptic-curve 0.13.4", + "rfc6979 0.4.0", "signature 2.0.0", ] @@ -1418,18 +1449,38 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ - "base16ct", - "crypto-bigint", - "der", + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", "digest 0.10.6", - "ff", + "ff 0.12.1", "generic-array", - "group", + "group 0.12.1", "hkdf", - "pem-rfc7468", - "pkcs8", + "pem-rfc7468 0.6.0", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.2", + "digest 0.10.6", + "ff 0.13.0", + "generic-array", + "group 0.13.0", + "pem-rfc7468 0.7.0", + "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1", + "sec1 0.7.1", "subtle", "zeroize", ] @@ -1515,6 +1566,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.1.17" @@ -1708,6 +1769,7 @@ checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1772,7 +1834,18 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff", + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", "rand_core 0.6.4", "subtle", ] @@ -2561,13 +2634,13 @@ dependencies = [ "log", "multiaddr", "multihash", - "p256 0.12.0", + "p256 0.13.2", "quick-protobuf", "quickcheck-ext", "rand 0.8.5", "ring", "rmp-serde", - "sec1", + "sec1 0.3.0", "serde", "serde_json", "sha2 0.10.6", @@ -3563,18 +3636,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" dependencies = [ "ecdsa 0.14.8", - "elliptic-curve", + "elliptic-curve 0.12.3", "sha2 0.10.6", ] [[package]] name = "p256" -version = "0.12.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c124b3cbce43bcbac68c58ec181d98ed6cc7e6d0aa7c3ba97b2563410b0e55" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa 0.15.1", - "elliptic-curve", + "ecdsa 0.16.6", + "elliptic-curve 0.13.4", "primeorder", "sha2 0.10.6", ] @@ -3586,7 +3659,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" dependencies = [ "ecdsa 0.14.8", - "elliptic-curve", + "elliptic-curve 0.12.3", "sha2 0.10.6", ] @@ -3684,6 +3757,15 @@ dependencies = [ "base64ct", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.2.0" @@ -3745,8 +3827,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" dependencies = [ - "der", - "spki", + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.5", + "spki 0.7.1", ] [[package]] @@ -3845,11 +3937,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "primeorder" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b54f7131b3dba65a2f414cf5bd25b66d4682e4608610668eae785750ba4c5b2" +checksum = "cf8d3875361e28f7753baefef104386e7aa47642c93023356d97fdef4003bfb5" dependencies = [ - "elliptic-curve", + "elliptic-curve 0.13.4", ] [[package]] @@ -4214,11 +4306,21 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" dependencies = [ - "crypto-bigint", + "crypto-bigint 0.4.9", "hmac 0.12.1", "zeroize", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + [[package]] name = "ring" version = "0.16.20" @@ -4466,10 +4568,24 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ - "base16ct", - "der", + "base16ct 0.1.1", + "der 0.6.1", + "generic-array", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.5", "generic-array", - "pkcs8", + "pkcs8 0.10.2", "subtle", "zeroize", ] @@ -4700,7 +4816,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" dependencies = [ "base64ct", - "der", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" +dependencies = [ + "base64ct", + "der 0.7.5", ] [[package]] @@ -5469,7 +5595,7 @@ dependencies = [ "ccm", "curve25519-dalek 3.2.0", "der-parser 8.1.0", - "elliptic-curve", + "elliptic-curve 0.12.3", "hkdf", "hmac 0.10.1", "log", @@ -5482,7 +5608,7 @@ dependencies = [ "rcgen 0.9.3", "ring", "rustls 0.19.1", - "sec1", + "sec1 0.3.0", "serde", "sha-1", "sha2 0.9.9", diff --git a/identity/Cargo.toml b/identity/Cargo.toml index fa57a8f72e2..b3b0541affd 100644 --- a/identity/Cargo.toml +++ b/identity/Cargo.toml @@ -19,7 +19,7 @@ libsecp256k1 = { version = "0.7.0", optional = true } log = "0.4" multiaddr = { version = "0.17.1", optional = true } multihash = { version = "0.17.0", default-features = false, features = ["std"], optional = true } -p256 = { version = "0.12", default-features = false, features = ["ecdsa", "std", "pem"], optional = true } +p256 = { version = "0.13", default-features = false, features = ["ecdsa", "std", "pem"], optional = true } quick-protobuf = { version = "0.8.1", optional = true } rand = { version = "0.8", optional = true } sec1 = { version = "0.3.0", features = ["std"], optional = true } # Activate `std` feature until https://github.com/RustCrypto/traits/pull/1131 is released. diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index 4f6394e3b1b..42ca70e7d7a 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -119,7 +119,7 @@ impl SecretKey { /// Try to parse a secret key from a byte buffer containing raw scalar of the key. pub fn try_from_bytes(buf: impl AsRef<[u8]>) -> Result { - SigningKey::from_bytes(buf.as_ref()) + SigningKey::from_bytes(buf.as_ref().into()) .map_err(|err| DecodingError::failed_to_parse("ecdsa p256 secret key", err)) .map(SecretKey) } From cc32b12d6dd62935018c936e77639b76b304f07c Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Tue, 2 May 2023 23:26:13 +0800 Subject: [PATCH 14/26] implement 'try_decode_pkcs8_der' for 'ecdsa::SecretKey' --- identity/src/ecdsa.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index 42ca70e7d7a..cbb6775f1a8 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -24,6 +24,7 @@ use super::error::DecodingError; use core::cmp; use core::fmt; use core::hash; +use p256::pkcs8::DecodePrivateKey; use p256::pkcs8::EncodePrivateKey; use p256::{ ecdsa::{ @@ -133,13 +134,13 @@ impl SecretKey { .to_vec() } - // Cannot implement this because error type does not implement `std::error::Error` - // pub fn try_decode_pkcs8_der(buf:&[u8])->Result{ - // match SigningKey::from_pkcs8_der(buf){ - // Ok(key) => Ok(SecretKey(key)), - // Err(e) => Err(DecodingError::failed_to_parse("ECDSA", e)), - // } - // } + /// Try to decode a secret key from a byte buffer in DER-encoded PKCS#8 format. + pub fn try_decode_pkcs8_der(buf: &[u8]) -> Result { + match SigningKey::from_pkcs8_der(buf) { + Ok(key) => Ok(SecretKey(key)), + Err(e) => Err(DecodingError::failed_to_parse("ECDSA", e)), + } + } } impl fmt::Debug for SecretKey { From 4329dc037b59e8aef0385f1996a3d576db3899d6 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Tue, 2 May 2023 23:26:47 +0800 Subject: [PATCH 15/26] changelog entry for #3863 --- identity/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/identity/CHANGELOG.md b/identity/CHANGELOG.md index c156928127a..f5c954c96d3 100644 --- a/identity/CHANGELOG.md +++ b/identity/CHANGELOG.md @@ -2,8 +2,11 @@ - Raise MSRV to 1.65. See [PR 3715]. +- Add PKCS#8 encoding/decoding support for ECDSA keys. + See [PR 3863]. [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 +[PR 3863]: https://github.com/libp2p/rust-libp2p/pull/3863 ## 0.1.2 From 37e663fd249b6b8e04646373466632702f936ca7 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Tue, 2 May 2023 23:34:24 +0800 Subject: [PATCH 16/26] encode/decode roundtrip test --- identity/src/ecdsa.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index cbb6775f1a8..b4a991ab802 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -304,4 +304,12 @@ mod tests { let invalid_msg = "h3ll0 w0rld".as_bytes(); assert!(!pk.verify(invalid_msg, &sig)); } + + #[test] + fn secret_key_encode_decode_roundtrip() { + let secret_key = SecretKey::generate(); + let encoded_bytes = secret_key.encode_pkcs8_der(); + let decoded_key = SecretKey::try_decode_pkcs8_der(&encoded_bytes).unwrap(); + assert_eq!(decoded_key.encode_pkcs8_der(), encoded_bytes) + } } From 8af2ca564e14211fc503393aa857208ea2d5d470 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Wed, 3 May 2023 12:40:11 +0800 Subject: [PATCH 17/26] change visibility of en/decode method to crate-level only --- identity/src/ecdsa.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index b4a991ab802..4bfd9edfde8 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -126,7 +126,7 @@ impl SecretKey { } /// Encode the secret key into DER-encoded PKCS#8 format. - pub fn encode_pkcs8_der(&self) -> Vec { + pub(crate) fn encode_pkcs8_der(&self) -> Vec { self.0 .to_pkcs8_der() .expect("Encoding to pkcs#8 format to succeed") @@ -135,7 +135,7 @@ impl SecretKey { } /// Try to decode a secret key from a byte buffer in DER-encoded PKCS#8 format. - pub fn try_decode_pkcs8_der(buf: &[u8]) -> Result { + pub(crate) fn try_decode_pkcs8_der(buf: &[u8]) -> Result { match SigningKey::from_pkcs8_der(buf) { Ok(key) => Ok(SecretKey(key)), Err(e) => Err(DecodingError::failed_to_parse("ECDSA", e)), From 782855258923c7845d998b9265fa49d70011195a Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Wed, 3 May 2023 13:03:19 +0800 Subject: [PATCH 18/26] implement protobuf en/decode for ecdsa keys --- identity/src/keypair.rs | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index 6f21125ff17..828fd516eb7 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -223,29 +223,25 @@ impl Keypair { } /// Encode a private key as protobuf structure. - #[cfg_attr( - not(feature = "ed25519"), - allow(unreachable_code, unused_variables, unused_mut) - )] pub fn to_protobuf_encoding(&self) -> Result, DecodingError> { use quick_protobuf::MessageWrite; - #[cfg(not(feature = "ed25519"))] - return Err(DecodingError::missing_feature("ed25519")); - #[allow(deprecated)] let pk: proto::PrivateKey = match self { #[cfg(feature = "ed25519")] Self::Ed25519(data) => proto::PrivateKey { Type: proto::KeyType::Ed25519, - Data: data.encode().to_vec(), + Data: data.to_bytes().to_vec(), }, #[cfg(all(feature = "rsa", not(target_arch = "wasm32")))] Self::Rsa(_) => return Err(DecodingError::encoding_unsupported("RSA")), #[cfg(feature = "secp256k1")] Self::Secp256k1(_) => return Err(DecodingError::encoding_unsupported("secp256k1")), #[cfg(feature = "ecdsa")] - Self::Ecdsa(_) => return Err(DecodingError::encoding_unsupported("ECDSA")), + Self::Ecdsa(data) => proto::PrivateKey { + Type: proto::KeyType::ECDSA, + Data: data.secret().encode_pkcs8_der(), + }, }; let mut buf = Vec::with_capacity(pk.get_size()); @@ -256,7 +252,6 @@ impl Keypair { } /// Decode a private key from a protobuf structure and parse it as a [`Keypair`]. - #[cfg_attr(not(feature = "ed25519"), allow(unused_mut))] pub fn from_protobuf_encoding(bytes: &[u8]) -> Result { use quick_protobuf::MessageRead; @@ -265,18 +260,21 @@ impl Keypair { .map_err(|e| DecodingError::bad_protobuf("private key bytes", e)) .map(zeroize::Zeroizing::new)?; + #[allow(deprecated, unreachable_code)] match private_key.Type { - #[cfg(feature = "ed25519")] - proto::KeyType::Ed25519 => - { - #[allow(deprecated)] - ed25519::Keypair::decode(&mut private_key.Data).map(Keypair::Ed25519) + proto::KeyType::Ed25519 => { + #[cfg(not(feature = "ed25519"))] + return Err(DecodingError::missing_feature("ed25519")); + ed25519::Keypair::try_from_bytes(&mut private_key.Data).map(Keypair::Ed25519) } - #[cfg(not(feature = "ed25519"))] - proto::KeyType::Ed25519 => Err(DecodingError::missing_feature("ed25519")), proto::KeyType::RSA => Err(DecodingError::decoding_unsupported("RSA")), proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")), - proto::KeyType::ECDSA => Err(DecodingError::decoding_unsupported("ECDSA")), + proto::KeyType::ECDSA => { + #[cfg(not(feature = "ecdsa"))] + return Err(DecodingError::missing_feature("ecdsa")); + ecdsa::SecretKey::try_decode_pkcs8_der(&mut private_key.Data) + .map(|key| Keypair::Ecdsa(key.into())) + } } } } From 5efbcb0e0b4e2e23547c6a178452329b38232065 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Wed, 3 May 2023 13:14:02 +0800 Subject: [PATCH 19/26] correct feature configuration --- identity/src/error.rs | 7 ------- identity/src/keypair.rs | 15 ++++++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/identity/src/error.rs b/identity/src/error.rs index 1ac945e71e9..0c86b346032 100644 --- a/identity/src/error.rs +++ b/identity/src/error.rs @@ -33,13 +33,6 @@ pub struct DecodingError { } impl DecodingError { - #[cfg(not(all( - feature = "ecdsa", - feature = "rsa", - feature = "secp256k1", - feature = "ed25519", - not(target_arch = "wasm32") - )))] pub(crate) fn missing_feature(feature_name: &'static str) -> Self { Self { msg: format!("cargo feature `{feature_name}` is not enabled"), diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index 828fd516eb7..c92a482ad5f 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -263,17 +263,18 @@ impl Keypair { #[allow(deprecated, unreachable_code)] match private_key.Type { proto::KeyType::Ed25519 => { - #[cfg(not(feature = "ed25519"))] - return Err(DecodingError::missing_feature("ed25519")); - ed25519::Keypair::try_from_bytes(&mut private_key.Data).map(Keypair::Ed25519) + #[cfg(feature = "ed25519")] + return ed25519::Keypair::try_from_bytes(&mut private_key.Data) + .map(Keypair::Ed25519); + Err(DecodingError::missing_feature("ed25519")) } proto::KeyType::RSA => Err(DecodingError::decoding_unsupported("RSA")), proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")), proto::KeyType::ECDSA => { - #[cfg(not(feature = "ecdsa"))] - return Err(DecodingError::missing_feature("ecdsa")); - ecdsa::SecretKey::try_decode_pkcs8_der(&mut private_key.Data) - .map(|key| Keypair::Ecdsa(key.into())) + #[cfg(feature = "ecdsa")] + return ecdsa::SecretKey::try_decode_pkcs8_der(&mut private_key.Data) + .map(|key| Keypair::Ecdsa(key.into())); + Err(DecodingError::missing_feature("ecdsa")) } } } From af8c068749f452dcf362aec4146dacd0759cf9f9 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Wed, 3 May 2023 14:04:55 +0800 Subject: [PATCH 20/26] fix: buffer not zeroized upon successful secret key decoding --- identity/src/ecdsa.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index 4bfd9edfde8..3f4ff3de7c2 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -34,6 +34,7 @@ use p256::{ EncodedPoint, }; use void::Void; +use zeroize::Zeroize; /// An ECDSA keypair generated using `secp256r1` curve. #[derive(Clone)] @@ -134,10 +135,13 @@ impl SecretKey { .to_vec() } - /// Try to decode a secret key from a byte buffer in DER-encoded PKCS#8 format. - pub(crate) fn try_decode_pkcs8_der(buf: &[u8]) -> Result { + /// Try to decode a secret key from a byte buffer in DER-encoded PKCS#8 format, zeroize the buffer on success. + pub(crate) fn try_decode_pkcs8_der(buf: &mut [u8]) -> Result { match SigningKey::from_pkcs8_der(buf) { - Ok(key) => Ok(SecretKey(key)), + Ok(key) => { + buf.zeroize(); + Ok(SecretKey(key)) + } Err(e) => Err(DecodingError::failed_to_parse("ECDSA", e)), } } @@ -309,7 +313,7 @@ mod tests { fn secret_key_encode_decode_roundtrip() { let secret_key = SecretKey::generate(); let encoded_bytes = secret_key.encode_pkcs8_der(); - let decoded_key = SecretKey::try_decode_pkcs8_der(&encoded_bytes).unwrap(); + let decoded_key = SecretKey::try_decode_pkcs8_der(encoded_bytes.clone().as_mut()).unwrap(); assert_eq!(decoded_key.encode_pkcs8_der(), encoded_bytes) } } From 26bc0f6cdeaef8855d9af40caf0092b4aa7105d1 Mon Sep 17 00:00:00 2001 From: DrHuangMHT Date: Wed, 3 May 2023 14:06:36 +0800 Subject: [PATCH 21/26] Update identity/CHANGELOG.md Co-authored-by: Thomas Eizinger --- identity/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/identity/CHANGELOG.md b/identity/CHANGELOG.md index f5c954c96d3..9aacfac822d 100644 --- a/identity/CHANGELOG.md +++ b/identity/CHANGELOG.md @@ -2,11 +2,12 @@ - Raise MSRV to 1.65. See [PR 3715]. -- Add PKCS#8 encoding/decoding support for ECDSA keys. +- Add support for exporting and importing ECDSA keys via the libp2p [protobuf format]. See [PR 3863]. [PR 3715]: https://github.com/libp2p/rust-libp2p/pull/3715 [PR 3863]: https://github.com/libp2p/rust-libp2p/pull/3863 +[protobuf format]: https://github.com/libp2p/specs/blob/master/peer-ids/peer-ids.md#keys ## 0.1.2 From 1c8d282c654c578dba1d39baf779c2eb6c399868 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Wed, 3 May 2023 16:16:37 +0800 Subject: [PATCH 22/26] protobuf roundtrip test for ecdsa keys --- Cargo.lock | 1 + identity/Cargo.toml | 1 + identity/src/ecdsa.rs | 8 -------- identity/src/keypair.rs | 34 ++++++++++++++++++++++++++++++++ identity/src/test/secp256r1.pk8 | Bin 0 -> 138 bytes 5 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 identity/src/test/secp256r1.pk8 diff --git a/Cargo.lock b/Cargo.lock index 358d9c651ea..e4508f979c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2630,6 +2630,7 @@ dependencies = [ "bs58", "criterion", "ed25519-dalek", + "hex-literal", "libsecp256k1", "log", "multiaddr", diff --git a/identity/Cargo.toml b/identity/Cargo.toml index b3b0541affd..bed30506888 100644 --- a/identity/Cargo.toml +++ b/identity/Cargo.toml @@ -45,6 +45,7 @@ base64 = "0.21.0" serde_json = "1.0" rmp-serde = "1.0" criterion = "0.4" +hex-literal = "0.4.1" [[bench]] name = "peer_id" diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index 3f4ff3de7c2..3eaa732cabf 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -308,12 +308,4 @@ mod tests { let invalid_msg = "h3ll0 w0rld".as_bytes(); assert!(!pk.verify(invalid_msg, &sig)); } - - #[test] - fn secret_key_encode_decode_roundtrip() { - let secret_key = SecretKey::generate(); - let encoded_bytes = secret_key.encode_pkcs8_der(); - let decoded_key = SecretKey::try_decode_pkcs8_der(encoded_bytes.clone().as_mut()).unwrap(); - assert_eq!(decoded_key.encode_pkcs8_der(), encoded_bytes) - } } diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index c92a482ad5f..b936e5cbef8 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -714,6 +714,40 @@ mod tests { assert_eq!(expected_peer_id, peer_id); } + #[test] + #[cfg(feature = "ecdsa")] + fn keypair_protobuf_roundtrip_ecdsa() { + let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!( + "08031220f0d87659b402f0d47589e7670ca0954036f87b2fbf11fafbc66f4de7c3eb10a2" + )) + .unwrap(); + let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!("0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004de6af15d8bc9b7f7c6eb8b32888d0da721d33f16af062306bafc64cdad741240cd61d6d9884c4899308ea25513a5cc03495ff88200dc7ae8e603ceb6698d2fee")).unwrap(); + + roundtrip_protobuf_encoding(&priv_key, &pub_key); + } + + fn roundtrip_protobuf_encoding(private_key: &Keypair, public_key: &PublicKey) { + assert_eq!(&private_key.public(), public_key); + + let encoded_priv = private_key.to_protobuf_encoding().unwrap(); + let decoded_priv = Keypair::from_protobuf_encoding(&encoded_priv).unwrap(); + + assert_eq!( + private_key.public().to_peer_id(), + decoded_priv.public().to_peer_id(), + "PeerId from roundtripped private key should be the same" + ); + + let encoded_public = private_key.public().encode_protobuf(); + let decoded_public = PublicKey::try_decode_protobuf(&encoded_public).unwrap(); + + assert_eq!( + private_key.public().to_peer_id(), + decoded_public.to_peer_id(), + "PeerId from roundtripped public key should be the same" + ); + } + #[test] #[cfg(feature = "peerid")] fn keypair_from_protobuf_encoding() { diff --git a/identity/src/test/secp256r1.pk8 b/identity/src/test/secp256r1.pk8 new file mode 100644 index 0000000000000000000000000000000000000000..81813a77b3e5703d99ca6318ee0862171d0a96f6 GIT binary patch literal 138 zcmXqLY-eI*Fc4;A*J|@PXUoLM#sOw9GqSVf8e}suGO{QXoHWsAT(-o<`RQAKo_}7) zl^mu=&f2zFU=!b|P1BX{FfVjrc4A=R(UTIooXHWw5tw&7E>8J($<)(NloV%O;$rF( qHm+q}SGDAghINqSB_3baZ~rQ{y`Lk(ctBRVxV~_yW&P%Jb?X7gpE3*p literal 0 HcmV?d00001 From 0c5c08d4f5f829117a50b396b064e9fbfee8d774 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 3 May 2023 11:20:34 +0200 Subject: [PATCH 23/26] Fix feature gates in test --- identity/src/peer_id.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/identity/src/peer_id.rs b/identity/src/peer_id.rs index 788e0b79666..51d9e4f1f6d 100644 --- a/identity/src/peer_id.rs +++ b/identity/src/peer_id.rs @@ -267,25 +267,27 @@ impl FromStr for PeerId { #[cfg(test)] mod tests { use super::*; - use crate::keypair::Keypair; #[test] + #[cfg(feature = "ed25519")] fn peer_id_is_public_key() { - let key = Keypair::generate_ed25519().public(); + let key = crate::Keypair::generate_ed25519().public(); let peer_id = key.to_peer_id(); assert_eq!(peer_id.is_public_key(&key), Some(true)); } #[test] + #[cfg(feature = "ed25519")] fn peer_id_into_bytes_then_from_bytes() { - let peer_id = Keypair::generate_ed25519().public().to_peer_id(); + let peer_id = crate::Keypair::generate_ed25519().public().to_peer_id(); let second = PeerId::from_bytes(&peer_id.to_bytes()).unwrap(); assert_eq!(peer_id, second); } #[test] + #[cfg(feature = "ed25519")] fn peer_id_to_base58_then_back() { - let peer_id = Keypair::generate_ed25519().public().to_peer_id(); + let peer_id = crate::Keypair::generate_ed25519().public().to_peer_id(); let second: PeerId = peer_id.to_base58().parse().unwrap(); assert_eq!(peer_id, second); } From 6c92bb3641b88d9ed34bac4f482f3ae6c13bd417 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 3 May 2023 11:20:44 +0200 Subject: [PATCH 24/26] Replace with correct test vector --- identity/src/keypair.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index b936e5cbef8..beb13adbb69 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -715,17 +715,18 @@ mod tests { } #[test] - #[cfg(feature = "ecdsa")] + #[cfg(all(feature = "ecdsa", feature = "peerid"))] fn keypair_protobuf_roundtrip_ecdsa() { let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!( - "08031220f0d87659b402f0d47589e7670ca0954036f87b2fbf11fafbc66f4de7c3eb10a2" + "0803128a01308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420122f33dad49e77dd1a467ac4b4b9432079d3ac0c110f9a608e86ff31a7552e55a14403420004ada418c4f1f7715ef1a365d9ae1e80f5d7069ab55ee19f1c4d77b44ea8dc9cbda558fe88dc32779c68573bf330daeeae1f44158a3b7d4b325230a8daf0d46dc5" )) .unwrap(); - let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!("0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004de6af15d8bc9b7f7c6eb8b32888d0da721d33f16af062306bafc64cdad741240cd61d6d9884c4899308ea25513a5cc03495ff88200dc7ae8e603ceb6698d2fee")).unwrap(); + let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!("0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004ada418c4f1f7715ef1a365d9ae1e80f5d7069ab55ee19f1c4d77b44ea8dc9cbda558fe88dc32779c68573bf330daeeae1f44158a3b7d4b325230a8daf0d46dc5")).unwrap(); roundtrip_protobuf_encoding(&priv_key, &pub_key); } + #[cfg(feature = "peerid")] fn roundtrip_protobuf_encoding(private_key: &Keypair, public_key: &PublicKey) { assert_eq!(&private_key.public(), public_key); From 3d850d0bf8e2557fb2edf038c485f0476e1dca0d Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Thu, 4 May 2023 10:10:20 +0800 Subject: [PATCH 25/26] drop pkcs8 and provide der support --- Cargo.lock | 2 +- identity/Cargo.toml | 2 +- identity/src/ecdsa.rs | 15 +++++++-------- identity/src/keypair.rs | 4 ++-- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4508f979c3..2338b85302f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2641,7 +2641,7 @@ dependencies = [ "rand 0.8.5", "ring", "rmp-serde", - "sec1 0.3.0", + "sec1 0.7.1", "serde", "serde_json", "sha2 0.10.6", diff --git a/identity/Cargo.toml b/identity/Cargo.toml index bed30506888..4a17e806554 100644 --- a/identity/Cargo.toml +++ b/identity/Cargo.toml @@ -22,7 +22,7 @@ multihash = { version = "0.17.0", default-features = false, features = ["std"], p256 = { version = "0.13", default-features = false, features = ["ecdsa", "std", "pem"], optional = true } quick-protobuf = { version = "0.8.1", optional = true } rand = { version = "0.8", optional = true } -sec1 = { version = "0.3.0", features = ["std"], optional = true } # Activate `std` feature until https://github.com/RustCrypto/traits/pull/1131 is released. +sec1 = { version = "0.7", default-features = false, optional = true } serde = { version = "1", optional = true, features = ["derive"] } sha2 = { version = "0.10.0", optional = true } thiserror = { version = "1.0", optional = true } diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs index 3eaa732cabf..90a8c3089c4 100644 --- a/identity/src/ecdsa.rs +++ b/identity/src/ecdsa.rs @@ -24,8 +24,6 @@ use super::error::DecodingError; use core::cmp; use core::fmt; use core::hash; -use p256::pkcs8::DecodePrivateKey; -use p256::pkcs8::EncodePrivateKey; use p256::{ ecdsa::{ signature::{Signer, Verifier}, @@ -33,6 +31,7 @@ use p256::{ }, EncodedPoint, }; +use sec1::{DecodeEcPrivateKey, EncodeEcPrivateKey}; use void::Void; use zeroize::Zeroize; @@ -126,18 +125,18 @@ impl SecretKey { .map(SecretKey) } - /// Encode the secret key into DER-encoded PKCS#8 format. - pub(crate) fn encode_pkcs8_der(&self) -> Vec { + /// Encode the secret key into DER-encoded byte buffer. + pub(crate) fn encode_der(&self) -> Vec { self.0 - .to_pkcs8_der() + .to_sec1_der() .expect("Encoding to pkcs#8 format to succeed") .to_bytes() .to_vec() } - /// Try to decode a secret key from a byte buffer in DER-encoded PKCS#8 format, zeroize the buffer on success. - pub(crate) fn try_decode_pkcs8_der(buf: &mut [u8]) -> Result { - match SigningKey::from_pkcs8_der(buf) { + /// Try to decode a secret key from a DER-encoded byte buffer, zeroize the buffer on success. + pub(crate) fn try_decode_der(buf: &mut [u8]) -> Result { + match SigningKey::from_sec1_der(buf) { Ok(key) => { buf.zeroize(); Ok(SecretKey(key)) diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index beb13adbb69..2c3e1fa53c4 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -240,7 +240,7 @@ impl Keypair { #[cfg(feature = "ecdsa")] Self::Ecdsa(data) => proto::PrivateKey { Type: proto::KeyType::ECDSA, - Data: data.secret().encode_pkcs8_der(), + Data: data.secret().encode_der(), }, }; @@ -272,7 +272,7 @@ impl Keypair { proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")), proto::KeyType::ECDSA => { #[cfg(feature = "ecdsa")] - return ecdsa::SecretKey::try_decode_pkcs8_der(&mut private_key.Data) + return ecdsa::SecretKey::try_decode_der(&mut private_key.Data) .map(|key| Keypair::Ecdsa(key.into())); Err(DecodingError::missing_feature("ecdsa")) } From 11b26fa38243908833959ab55f15fe5b91b5d9a6 Mon Sep 17 00:00:00 2001 From: drHuangMHT Date: Thu, 4 May 2023 11:15:25 +0800 Subject: [PATCH 26/26] update test vector for ecdsa --- identity/src/keypair.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index 2c3e1fa53c4..0b36ea31be9 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -718,10 +718,10 @@ mod tests { #[cfg(all(feature = "ecdsa", feature = "peerid"))] fn keypair_protobuf_roundtrip_ecdsa() { let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!( - "0803128a01308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420122f33dad49e77dd1a467ac4b4b9432079d3ac0c110f9a608e86ff31a7552e55a14403420004ada418c4f1f7715ef1a365d9ae1e80f5d7069ab55ee19f1c4d77b44ea8dc9cbda558fe88dc32779c68573bf330daeeae1f44158a3b7d4b325230a8daf0d46dc5" + "08031279307702010104203E5B1FE9712E6C314942A750BD67485DE3C1EFE85B1BFB520AE8F9AE3DFA4A4CA00A06082A8648CE3D030107A14403420004DE3D300FA36AE0E8F5D530899D83ABAB44ABF3161F162A4BC901D8E6ECDA020E8B6D5F8DA30525E71D6851510C098E5C47C646A597FB4DCEC034E9F77C409E62" )) .unwrap(); - let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!("0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004ada418c4f1f7715ef1a365d9ae1e80f5d7069ab55ee19f1c4d77b44ea8dc9cbda558fe88dc32779c68573bf330daeeae1f44158a3b7d4b325230a8daf0d46dc5")).unwrap(); + let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!("0803125b3059301306072a8648ce3d020106082a8648ce3d03010703420004de3d300fa36ae0e8f5d530899d83abab44abf3161f162a4bc901d8e6ecda020e8b6d5f8da30525e71d6851510c098e5c47c646a597fb4dcec034e9f77c409e62")).unwrap(); roundtrip_protobuf_encoding(&priv_key, &pub_key); }