refactor(identity): follow naming conventions for conversion methods

This PR renames some method names that don't follow Rust naming conventions or behave differently from what the name suggests:
- Enforce "try" prefix on all methods that return `Result`.
- Enforce "encode" method name for methods that return encoded bytes.
- Enforce "to_bytes" method name for methods that return raw bytes.
- Enforce "decode" method name for methods that convert encoded key.
- Enforce "from_bytes" method name for methods that convert raw bytes.

Pull-Request: #3775.
This commit is contained in:
DrHuangMHT
2023-04-14 16:55:13 +08:00
committed by GitHub
parent 8ffcff9624
commit 058c2d85ec
23 changed files with 490 additions and 109 deletions

2
Cargo.lock generated
View File

@ -2493,7 +2493,7 @@ dependencies = [
[[package]]
name = "libp2p-identity"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"asn1_der",
"base64 0.21.0",

View File

@ -76,7 +76,7 @@ impl SignedEnvelope {
use quick_protobuf::MessageWrite;
let envelope = proto::Envelope {
public_key: self.key.to_protobuf_encoding(),
public_key: self.key.encode_protobuf(),
payload_type: self.payload_type,
payload: self.payload,
signature: self.signature,
@ -101,7 +101,7 @@ impl SignedEnvelope {
proto::Envelope::from_reader(&mut reader, bytes).map_err(DecodeError::from)?;
Ok(Self {
key: PublicKey::from_protobuf_encoding(&envelope.public_key)?,
key: PublicKey::try_decode_protobuf(&envelope.public_key)?,
payload_type: envelope.payload_type.to_vec(),
payload: envelope.payload.to_vec(),
signature: envelope.signature.to_vec(),

View File

@ -1,3 +1,10 @@
## 0.1.2 - unreleased
- Follow Rust naming conventions for conversion methods.
See [PR 3775].
[PR 3775]: https://github.com/libp2p/rust-libp2p/pull/3775
## 0.1.1
- Add `From` impl for specific keypairs.

View File

@ -1,6 +1,6 @@
[package]
name = "libp2p-identity"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
description = "Data structures and algorithms for identifying peers in libp2p."
rust-version = "1.60.0"

View File

@ -33,7 +33,7 @@ use p256::{
};
use void::Void;
/// An ECDSA keypair.
/// An ECDSA keypair generated using `secp256r1` curve.
#[derive(Clone)]
pub struct Keypair {
secret: SecretKey,
@ -85,7 +85,7 @@ impl From<Keypair> for SecretKey {
}
}
/// An ECDSA secret key.
/// An ECDSA secret key generated using `secp256r1` curve.
#[derive(Clone)]
pub struct SecretKey(SigningKey);
@ -102,14 +102,23 @@ impl SecretKey {
signature.as_bytes().to_owned()
}
/// Encode a secret key into a byte buffer.
/// Convert a secret key into a byte buffer containing raw scalar of the key.
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes().to_vec()
}
/// Decode a secret key from a byte buffer.
/// Decode a secret key from a byte buffer containing raw scalar of the key.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `SecretKey::try_from_bytes` instead"
)]
pub fn from_bytes(buf: &[u8]) -> Result<Self, DecodingError> {
SigningKey::from_bytes(buf)
Self::try_from_bytes(buf)
}
/// 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<SecretKey, DecodingError> {
SigningKey::from_bytes(buf.as_ref())
.map_err(|err| DecodingError::failed_to_parse("ecdsa p256 secret key", err))
.map(SecretKey)
}
@ -135,8 +144,17 @@ impl PublicKey {
self.0.verify(msg, &sig).is_ok()
}
/// Decode a public key from a byte buffer without compression.
/// Decode a public key from a byte buffer containing raw components of a key with or without compression.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_from_bytes` instead."
)]
pub fn from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
Self::try_from_bytes(k)
}
/// Try to parse a public key from a byte buffer containing raw components of a key with or without compression.
pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
let enc_pt = EncodedPoint::from_bytes(k)
.map_err(|e| DecodingError::failed_to_parse("ecdsa p256 encoded point", e))?;
@ -145,7 +163,7 @@ impl PublicKey {
.map(PublicKey)
}
/// Encode a public key into a byte buffer without compression.
/// Convert a public key into a byte buffer containing raw components of the key without compression.
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_encoded_point(false).as_bytes().to_owned()
}
@ -157,11 +175,20 @@ impl PublicKey {
}
/// Decode a public key into a DER encoded byte buffer as defined by SEC1 standard.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_decode_der` instead."
)]
pub fn decode_der(k: &[u8]) -> Result<PublicKey, DecodingError> {
Self::try_decode_der(k)
}
/// Try to decode a public key from a DER encoded byte buffer as defined by SEC1 standard.
pub fn try_decode_der(k: &[u8]) -> Result<PublicKey, DecodingError> {
let buf = Self::del_asn1_header(k).ok_or_else(|| {
DecodingError::failed_to_parse::<Void, _>("ASN.1-encoded ecdsa p256 public key", None)
})?;
Self::from_bytes(buf)
Self::try_from_bytes(buf)
}
// ecPublicKey (ANSI X9.62 public key type) OID: 1.2.840.10045.2.1

View File

@ -41,15 +41,35 @@ impl Keypair {
/// Encode the keypair into a byte array by concatenating the bytes
/// of the secret scalar and the compressed public point,
/// an informal standard for encoding Ed25519 keypairs.
#[deprecated(since = "0.2.0", note = "Renamed to `Keypair::to_bytes`")]
pub fn encode(&self) -> [u8; 64] {
self.to_bytes()
}
/// Convert the keypair into a byte array by concatenating the bytes
/// of the secret scalar and the compressed public point,
/// an informal standard for encoding Ed25519 keypairs.
pub fn to_bytes(&self) -> [u8; 64] {
self.0.to_bytes()
}
/// Decode a keypair from the [binary format](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5)
/// produced by [`Keypair::encode`], zeroing the input on success.
/// produced by [`Keypair::to_bytes`], zeroing the input on success.
///
/// Note that this binary format is the same as `ed25519_dalek`'s and `ed25519_zebra`'s.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `Keypair::try_from_bytes` instead."
)]
pub fn decode(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
Self::try_from_bytes(kp)
}
/// Try to parse a keypair from the [binary format](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5)
/// produced by [`Keypair::to_bytes`], zeroing the input on success.
///
/// Note that this binary format is the same as `ed25519_dalek`'s and `ed25519_zebra`'s.
pub fn try_from_bytes(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
ed25519::Keypair::from_bytes(kp)
.map(|k| {
kp.zeroize();
@ -70,7 +90,7 @@ impl Keypair {
/// Get the secret key of this keypair.
pub fn secret(&self) -> SecretKey {
SecretKey::from_bytes(&mut self.0.secret.to_bytes())
SecretKey::try_from_bytes(&mut self.0.secret.to_bytes())
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
}
}
@ -86,7 +106,7 @@ impl fmt::Debug for Keypair {
impl Clone for Keypair {
fn clone(&self) -> Keypair {
let mut sk_bytes = self.0.secret.to_bytes();
let secret = SecretKey::from_bytes(&mut sk_bytes)
let secret = SecretKey::try_from_bytes(&mut sk_bytes)
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
.0;
@ -164,12 +184,31 @@ impl PublicKey {
/// Encode the public key into a byte array in compressed form, i.e.
/// where one coordinate is represented by a single bit.
#[deprecated(
since = "0.2.0",
note = "Renamed to `PublicKey::to_bytes` to reflect actual behaviour."
)]
pub fn encode(&self) -> [u8; 32] {
self.to_bytes()
}
/// Convert the public key to a byte array in compressed form, i.e.
/// where one coordinate is represented by a single bit.
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_bytes()
}
/// Decode a public key from a byte array as produced by `encode`.
/// Decode a public key from a byte array as produced by `to_bytes`.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_from_bytes` instead."
)]
pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
Self::try_from_bytes(k)
}
/// Try to parse a public key from a byte array containing the actual key as produced by `to_bytes`.
pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
ed25519::PublicKey::from_bytes(k)
.map_err(|e| DecodingError::failed_to_parse("Ed25519 public key", e))
.map(PublicKey)
@ -189,7 +228,8 @@ impl AsRef<[u8]> for SecretKey {
impl Clone for SecretKey {
fn clone(&self) -> SecretKey {
let mut sk_bytes = self.0.to_bytes();
Self::from_bytes(&mut sk_bytes).expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
Self::try_from_bytes(&mut sk_bytes)
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
}
}
@ -214,7 +254,20 @@ impl SecretKey {
/// Create an Ed25519 secret key from a byte slice, zeroing the input on success.
/// If the bytes do not constitute a valid Ed25519 secret key, an error is
/// returned.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `SecretKey::try_from_bytes` instead."
)]
#[allow(unused_mut)]
pub fn from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
Self::try_from_bytes(sk_bytes)
}
/// Try to parse an Ed25519 secret key from a byte slice
/// containing the actual key, zeroing the input on success.
/// If the bytes do not constitute a valid Ed25519 secret key, an error is
/// returned.
pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
let sk_bytes = sk_bytes.as_mut();
let secret = ed25519::SecretKey::from_bytes(&*sk_bytes)
.map_err(|e| DecodingError::failed_to_parse("Ed25519 secret key", e))?;
@ -236,8 +289,8 @@ mod tests {
fn ed25519_keypair_encode_decode() {
fn prop() -> bool {
let kp1 = Keypair::generate();
let mut kp1_enc = kp1.encode();
let kp2 = Keypair::decode(&mut kp1_enc).unwrap();
let mut kp1_enc = kp1.to_bytes();
let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap();
eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0)
}
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
@ -248,7 +301,7 @@ mod tests {
fn prop() -> bool {
let kp1 = Keypair::generate();
let mut sk = kp1.0.secret.to_bytes();
let kp2 = Keypair::from(SecretKey::from_bytes(&mut sk).unwrap());
let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap());
eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
}
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);

View File

@ -23,6 +23,8 @@
use std::error::Error;
use std::fmt;
use crate::KeyType;
/// An error during decoding of key material.
#[derive(Debug)]
pub struct DecodingError {
@ -156,3 +158,26 @@ impl Error for SigningError {
self.source.as_ref().map(|s| &**s as &dyn Error)
}
}
/// Error produced when failing to convert [`Keypair`](crate::Keypair) to a more concrete keypair.
#[derive(Debug)]
pub struct OtherVariantError {
actual: KeyType,
}
impl OtherVariantError {
pub(crate) fn new(actual: KeyType) -> OtherVariantError {
OtherVariantError { actual }
}
}
impl fmt::Display for OtherVariantError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&format!(
"Cannot convert to the given type, the actual key type inside is {}",
self.actual
))
}
}
impl Error for OtherVariantError {}

View File

@ -18,8 +18,9 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use crate::error::OtherVariantError;
use crate::error::{DecodingError, SigningError};
use crate::proto;
use crate::{proto, KeyType};
use quick_protobuf::{BytesReader, Writer};
use std::convert::TryFrom;
@ -59,28 +60,28 @@ pub enum Keypair {
#[cfg(feature = "ed25519")]
#[deprecated(
since = "0.1.0",
note = "This enum will be made opaque in the future, use `Keypair::into_ed25519` instead."
note = "This enum will be made opaque in the future, use `Keypair::try_into_ed25519` instead."
)]
Ed25519(ed25519::Keypair),
/// An RSA keypair.
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
#[deprecated(
since = "0.1.0",
note = "This enum will be made opaque in the future, use `Keypair::into_rsa` instead."
note = "This enum will be made opaque in the future, use `Keypair::try_into_rsa` instead."
)]
Rsa(rsa::Keypair),
/// A Secp256k1 keypair.
#[cfg(feature = "secp256k1")]
#[deprecated(
since = "0.1.0",
note = "This enum will be made opaque in the future, use `Keypair::into_secp256k1` instead."
note = "This enum will be made opaque in the future, use `Keypair::try_into_secp256k1` instead."
)]
Secp256k1(secp256k1::Keypair),
/// An ECDSA keypair.
#[cfg(feature = "ecdsa")]
#[deprecated(
since = "0.1.0",
note = "This enum will be made opaque in the future, use `Keypair::into_ecdsa` instead."
note = "This enum will be made opaque in the future, use `Keypair::try_into_ecdsa` instead."
)]
Ecdsa(ecdsa::Keypair),
}
@ -108,43 +109,59 @@ impl Keypair {
}
#[cfg(feature = "ed25519")]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_ed25519` instead."
)]
pub fn into_ed25519(self) -> Option<ed25519::Keypair> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
Keypair::Ed25519(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(feature = "ed25519")]
pub fn try_into_ed25519(self) -> Result<ed25519::Keypair, OtherVariantError> {
self.try_into()
}
#[cfg(feature = "secp256k1")]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_secp256k1` instead."
)]
pub fn into_secp256k1(self) -> Option<secp256k1::Keypair> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
Keypair::Secp256k1(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(feature = "secp256k1")]
pub fn try_into_secp256k1(self) -> Result<secp256k1::Keypair, OtherVariantError> {
self.try_into()
}
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_rsa` instead."
)]
pub fn into_rsa(self) -> Option<rsa::Keypair> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
Keypair::Rsa(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
pub fn try_into_rsa(self) -> Result<rsa::Keypair, OtherVariantError> {
self.try_into()
}
#[cfg(feature = "ecdsa")]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_ecdsa` instead."
)]
pub fn into_ecdsa(self) -> Option<ecdsa::Keypair> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
Keypair::Ecdsa(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(feature = "ecdsa")]
pub fn try_into_ecdsa(self) -> Result<ecdsa::Keypair, OtherVariantError> {
self.try_into()
}
/// Decode an keypair from a DER-encoded secret key in PKCS#8 PrivateKeyInfo
@ -300,6 +317,78 @@ impl From<rsa::Keypair> for Keypair {
}
}
#[cfg(feature = "ed25519")]
impl TryInto<ed25519::Keypair> for Keypair {
type Error = OtherVariantError;
fn try_into(self) -> Result<ed25519::Keypair, Self::Error> {
#[allow(deprecated)]
match self {
Keypair::Ed25519(inner) => Ok(inner),
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
Keypair::Rsa(_) => Err(OtherVariantError::new(KeyType::RSA)),
#[cfg(feature = "secp256k1")]
Keypair::Secp256k1(_) => Err(OtherVariantError::new(KeyType::Secp256k1)),
#[cfg(feature = "ecdsa")]
Keypair::Ecdsa(_) => Err(OtherVariantError::new(KeyType::Ecdsa)),
}
}
}
#[cfg(feature = "ecdsa")]
impl TryInto<ecdsa::Keypair> for Keypair {
type Error = OtherVariantError;
fn try_into(self) -> Result<ecdsa::Keypair, Self::Error> {
#[allow(deprecated)]
match self {
Keypair::Ecdsa(inner) => Ok(inner),
#[cfg(feature = "ed25519")]
Keypair::Ed25519(_) => Err(OtherVariantError::new(KeyType::Ed25519)),
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
Keypair::Rsa(_) => Err(OtherVariantError::new(KeyType::RSA)),
#[cfg(feature = "secp256k1")]
Keypair::Secp256k1(_) => Err(OtherVariantError::new(KeyType::Secp256k1)),
}
}
}
#[cfg(feature = "secp256k1")]
impl TryInto<secp256k1::Keypair> for Keypair {
type Error = OtherVariantError;
fn try_into(self) -> Result<secp256k1::Keypair, Self::Error> {
#[allow(deprecated)]
match self {
Keypair::Secp256k1(inner) => Ok(inner),
#[cfg(feature = "ed25519")]
Keypair::Ed25519(_) => Err(OtherVariantError::new(KeyType::Ed25519)),
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
Keypair::Rsa(_) => Err(OtherVariantError::new(KeyType::RSA)),
#[cfg(feature = "ecdsa")]
Keypair::Ecdsa(_) => Err(OtherVariantError::new(KeyType::Ecdsa)),
}
}
}
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
impl TryInto<rsa::Keypair> for Keypair {
type Error = OtherVariantError;
fn try_into(self) -> Result<rsa::Keypair, Self::Error> {
#[allow(deprecated)]
match self {
Keypair::Rsa(inner) => Ok(inner),
#[cfg(feature = "ed25519")]
Keypair::Ed25519(_) => Err(OtherVariantError::new(KeyType::Ed25519)),
#[cfg(feature = "secp256k1")]
Keypair::Secp256k1(_) => Err(OtherVariantError::new(KeyType::Secp256k1)),
#[cfg(feature = "ecdsa")]
Keypair::Ecdsa(_) => Err(OtherVariantError::new(KeyType::Ecdsa)),
}
}
}
/// The public key of a node's identity keypair.
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum PublicKey {
@ -356,48 +445,71 @@ impl PublicKey {
}
#[cfg(feature = "ed25519")]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_ed25519` instead."
)]
pub fn into_ed25519(self) -> Option<ed25519::PublicKey> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
PublicKey::Ed25519(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(feature = "ed25519")]
pub fn try_into_ed25519(self) -> Result<ed25519::PublicKey, OtherVariantError> {
self.try_into()
}
#[cfg(feature = "secp256k1")]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_secp256k1` instead."
)]
pub fn into_secp256k1(self) -> Option<secp256k1::PublicKey> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
PublicKey::Secp256k1(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(feature = "secp256k1")]
pub fn try_into_secp256k1(self) -> Result<secp256k1::PublicKey, OtherVariantError> {
self.try_into()
}
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_rsa` instead."
)]
pub fn into_rsa(self) -> Option<rsa::PublicKey> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
PublicKey::Rsa(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
pub fn try_into_rsa(self) -> Result<rsa::PublicKey, OtherVariantError> {
self.try_into()
}
#[cfg(feature = "ecdsa")]
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_ecdsa` instead."
)]
pub fn into_ecdsa(self) -> Option<ecdsa::PublicKey> {
#[allow(deprecated)]
#[allow(unreachable_patterns)]
match self {
PublicKey::Ecdsa(inner) => Some(inner),
_ => None,
self.try_into().ok()
}
#[cfg(feature = "ecdsa")]
pub fn try_into_ecdsa(self) -> Result<ecdsa::PublicKey, OtherVariantError> {
self.try_into()
}
/// Encode the public key into a protobuf structure for storage or
/// exchange with other nodes.
#[deprecated(since = "0.2.0", note = "Renamed to `PublicKey::encode_protobuf`.")]
pub fn to_protobuf_encoding(&self) -> Vec<u8> {
Self::encode_protobuf(self)
}
/// Encode the public key into a protobuf structure for storage or
/// exchange with other nodes.
pub fn encode_protobuf(&self) -> Vec<u8> {
use quick_protobuf::MessageWrite;
let public_key = proto::PublicKey::from(self);
@ -413,7 +525,17 @@ impl PublicKey {
/// Decode a public key from a protobuf structure, e.g. read from storage
/// or received from another node.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_decode_protobuf` instead."
)]
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
Self::try_decode_protobuf(bytes)
}
/// Decode a public key from a protobuf structure, e.g. read from storage
/// or received from another node.
pub fn try_decode_protobuf(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
use quick_protobuf::MessageRead;
let mut reader = BytesReader::from_bytes(bytes);
@ -475,6 +597,78 @@ impl TryFrom<proto::PublicKey> for PublicKey {
}
}
#[cfg(feature = "ed25519")]
impl TryInto<ed25519::PublicKey> for PublicKey {
type Error = OtherVariantError;
fn try_into(self) -> Result<ed25519::PublicKey, Self::Error> {
#[allow(deprecated)]
match self {
PublicKey::Ed25519(inner) => Ok(inner),
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
PublicKey::Rsa(_) => Err(OtherVariantError::new(KeyType::RSA)),
#[cfg(feature = "secp256k1")]
PublicKey::Secp256k1(_) => Err(OtherVariantError::new(KeyType::Secp256k1)),
#[cfg(feature = "ecdsa")]
PublicKey::Ecdsa(_) => Err(OtherVariantError::new(KeyType::Ecdsa)),
}
}
}
#[cfg(feature = "ecdsa")]
impl TryInto<ecdsa::PublicKey> for PublicKey {
type Error = OtherVariantError;
fn try_into(self) -> Result<ecdsa::PublicKey, Self::Error> {
#[allow(deprecated)]
match self {
PublicKey::Ecdsa(inner) => Ok(inner),
#[cfg(feature = "ed25519")]
PublicKey::Ed25519(_) => Err(OtherVariantError::new(KeyType::Ed25519)),
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
PublicKey::Rsa(_) => Err(OtherVariantError::new(KeyType::RSA)),
#[cfg(feature = "secp256k1")]
PublicKey::Secp256k1(_) => Err(OtherVariantError::new(KeyType::Secp256k1)),
}
}
}
#[cfg(feature = "secp256k1")]
impl TryInto<secp256k1::PublicKey> for PublicKey {
type Error = OtherVariantError;
fn try_into(self) -> Result<secp256k1::PublicKey, Self::Error> {
#[allow(deprecated)]
match self {
PublicKey::Secp256k1(inner) => Ok(inner),
#[cfg(feature = "ed25519")]
PublicKey::Ed25519(_) => Err(OtherVariantError::new(KeyType::Ed25519)),
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
PublicKey::Rsa(_) => Err(OtherVariantError::new(KeyType::RSA)),
#[cfg(feature = "ecdsa")]
PublicKey::Ecdsa(_) => Err(OtherVariantError::new(KeyType::Ecdsa)),
}
}
}
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
impl TryInto<rsa::PublicKey> for PublicKey {
type Error = OtherVariantError;
fn try_into(self) -> Result<rsa::PublicKey, Self::Error> {
#[allow(deprecated)]
match self {
PublicKey::Rsa(inner) => Ok(inner),
#[cfg(feature = "ed25519")]
PublicKey::Ed25519(_) => Err(OtherVariantError::new(KeyType::Ed25519)),
#[cfg(feature = "secp256k1")]
PublicKey::Secp256k1(_) => Err(OtherVariantError::new(KeyType::Secp256k1)),
#[cfg(feature = "ecdsa")]
PublicKey::Ecdsa(_) => Err(OtherVariantError::new(KeyType::Ecdsa)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -121,7 +121,27 @@ impl From<&PublicKey> for proto::PublicKey {
}
}
pub use error::{DecodingError, SigningError};
pub use error::{DecodingError, OtherVariantError, SigningError};
pub use keypair::{Keypair, PublicKey};
#[cfg(feature = "peerid")]
pub use peer_id::{ParseError, PeerId};
#[derive(Debug, PartialEq, Eq)]
/// The type of key a `KeyPair` is holding.
pub enum KeyType {
Ed25519,
RSA,
Secp256k1,
Ecdsa,
}
impl std::fmt::Display for KeyType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
KeyType::Ed25519 => f.write_str("Ed25519"),
KeyType::RSA => f.write_str("RSA"),
KeyType::Secp256k1 => f.write_str("Secp256k1"),
KeyType::Ecdsa => f.write_str("Ecdsa"),
}
}
}

View File

@ -66,7 +66,7 @@ impl fmt::Display for PeerId {
impl PeerId {
/// Builds a `PeerId` from a public key.
pub fn from_public_key(key: &crate::keypair::PublicKey) -> PeerId {
let key_enc = key.to_protobuf_encoding();
let key_enc = key.encode_protobuf();
let multihash = if key_enc.len() <= MAX_INLINE_KEY_LENGTH {
Multihash::wrap(MULTIHASH_IDENTITY_CODE, &key_enc)
@ -141,7 +141,7 @@ impl PeerId {
let alg = Code::try_from(self.multihash.code())
.expect("Internal multihash is always a valid `Code`");
let enc = public_key.to_protobuf_encoding();
let enc = public_key.encode_protobuf();
Some(alg.digest(&enc) == self.multihash)
}
}

View File

@ -46,7 +46,16 @@ impl Keypair {
/// format (i.e. unencrypted) as defined in [RFC5208].
///
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
#[deprecated(since = "0.2.0", note = "Renamed to `Keypair::try_decode_pkcs8`.")]
pub fn from_pkcs8(der: &mut [u8]) -> Result<Keypair, DecodingError> {
Self::try_decode_pkcs8(der)
}
/// Decode an RSA keypair from a DER-encoded private key in PKCS#8 PrivateKeyInfo
/// format (i.e. unencrypted) as defined in [RFC5208].
///
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
pub fn try_decode_pkcs8(der: &mut [u8]) -> Result<Keypair, DecodingError> {
let kp = RsaKeyPair::from_pkcs8(der)
.map_err(|e| DecodingError::failed_to_parse("RSA PKCS#8 PrivateKeyInfo", e))?;
der.zeroize();
@ -109,7 +118,17 @@ impl PublicKey {
/// Decode an RSA public key from a DER-encoded X.509 SubjectPublicKeyInfo
/// structure. See also `encode_x509`.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_decode_x509` instead."
)]
pub fn decode_x509(pk: &[u8]) -> Result<PublicKey, DecodingError> {
Self::try_decode_x509(pk)
}
/// Decode an RSA public key from a DER-encoded X.509 SubjectPublicKeyInfo
/// structure. See also `encode_x509`.
pub fn try_decode_x509(pk: &[u8]) -> Result<PublicKey, DecodingError> {
Asn1SubjectPublicKeyInfo::decode(pk)
.map_err(|e| DecodingError::failed_to_parse("RSA X.509", e))
.map(|spki| spki.subjectPublicKey.0)
@ -317,22 +336,22 @@ mod tests {
impl Arbitrary for SomeKeypair {
fn arbitrary(g: &mut Gen) -> SomeKeypair {
let mut key = g.choose(&[KEY1, KEY2, KEY3]).unwrap().to_vec();
SomeKeypair(Keypair::from_pkcs8(&mut key).unwrap())
SomeKeypair(Keypair::try_decode_pkcs8(&mut key).unwrap())
}
}
#[test]
fn rsa_from_pkcs8() {
assert!(Keypair::from_pkcs8(&mut KEY1.to_vec()).is_ok());
assert!(Keypair::from_pkcs8(&mut KEY2.to_vec()).is_ok());
assert!(Keypair::from_pkcs8(&mut KEY3.to_vec()).is_ok());
assert!(Keypair::try_decode_pkcs8(&mut KEY1.to_vec()).is_ok());
assert!(Keypair::try_decode_pkcs8(&mut KEY2.to_vec()).is_ok());
assert!(Keypair::try_decode_pkcs8(&mut KEY3.to_vec()).is_ok());
}
#[test]
fn rsa_x509_encode_decode() {
fn prop(SomeKeypair(kp): SomeKeypair) -> Result<bool, String> {
let pk = kp.public();
PublicKey::decode_x509(&pk.encode_x509())
PublicKey::try_decode_x509(&pk.encode_x509())
.map_err(|e| e.to_string())
.map(|pk2| pk2 == pk)
}

View File

@ -97,7 +97,21 @@ impl SecretKey {
/// error is returned.
///
/// Note that the expected binary format is the same as `libsecp256k1`'s.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `SecretKey::try_from_bytes` instead."
)]
#[allow(unused_mut)]
pub fn from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
Self::try_from_bytes(sk)
}
/// Create a secret key from a byte slice, zeroing the slice on success.
/// If the bytes do not constitute a valid Secp256k1 secret key, an
/// error is returned.
///
/// Note that the expected binary format is the same as `libsecp256k1`'s.
pub fn try_from_bytes(mut sk: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
let sk_bytes = sk.as_mut();
let secret = libsecp256k1::SecretKey::parse_slice(&*sk_bytes)
.map_err(|e| DecodingError::failed_to_parse("parse secp256k1 secret key", e))?;
@ -118,7 +132,7 @@ impl SecretKey {
.and_then(Vec::load)
.map_err(|e| DecodingError::failed_to_parse("secp256k1 SecretKey bytes", e))?;
let sk = SecretKey::from_bytes(&mut sk_bytes)?;
let sk = SecretKey::try_from_bytes(&mut sk_bytes)?;
sk_bytes.zeroize();
der_obj.zeroize();
Ok(sk)
@ -157,7 +171,7 @@ pub struct PublicKey(libsecp256k1::PublicKey);
impl fmt::Debug for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("PublicKey(compressed): ")?;
for byte in &self.encode() {
for byte in &self.to_bytes() {
write!(f, "{byte:x}")?;
}
Ok(())
@ -166,25 +180,25 @@ impl fmt::Debug for PublicKey {
impl cmp::PartialEq for PublicKey {
fn eq(&self, other: &Self) -> bool {
self.encode().eq(&other.encode())
self.to_bytes().eq(&other.to_bytes())
}
}
impl hash::Hash for PublicKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.encode().hash(state);
self.to_bytes().hash(state);
}
}
impl cmp::PartialOrd for PublicKey {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
self.encode().partial_cmp(&other.encode())
self.to_bytes().partial_cmp(&other.to_bytes())
}
}
impl cmp::Ord for PublicKey {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.encode().cmp(&other.encode())
self.to_bytes().cmp(&other.to_bytes())
}
}
@ -203,18 +217,44 @@ impl PublicKey {
/// Encode the public key in compressed form, i.e. with one coordinate
/// represented by a single bit.
#[deprecated(since = "0.2.0", note = "Renamed to `PublicKey::to_bytes`.")]
pub fn encode(&self) -> [u8; 33] {
self.to_bytes()
}
/// Convert the public key to a byte buffer in compressed form, i.e. with one coordinate
/// represented by a single bit.
pub fn to_bytes(&self) -> [u8; 33] {
self.0.serialize_compressed()
}
/// Encode the public key in uncompressed form.
#[deprecated(
since = "0.2.0",
note = "Renamed to `PublicKey::to_bytes_uncompressed`."
)]
pub fn encode_uncompressed(&self) -> [u8; 65] {
self.to_bytes_uncompressed()
}
/// Convert the public key to a byte buffer in uncompressed form.
pub fn to_bytes_uncompressed(&self) -> [u8; 65] {
self.0.serialize()
}
/// Decode a public key from a byte slice in the the format produced
/// by `encode`.
#[deprecated(
since = "0.2.0",
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_from_bytes` instead."
)]
pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
Self::try_from_bytes(k)
}
/// Decode a public key from a byte slice in the the format produced
/// by `encode`.
pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
libsecp256k1::PublicKey::parse_slice(k, Some(libsecp256k1::PublicKeyFormat::Compressed))
.map_err(|e| DecodingError::failed_to_parse("secp256k1 public key", e))
.map(PublicKey)
@ -230,7 +270,7 @@ mod tests {
let sk1 = SecretKey::generate();
let mut sk_bytes = [0; 32];
sk_bytes.copy_from_slice(&sk1.0.serialize()[..]);
let sk2 = SecretKey::from_bytes(&mut sk_bytes).unwrap();
let sk2 = SecretKey::try_from_bytes(&mut sk_bytes).unwrap();
assert_eq!(sk1.0.serialize(), sk2.0.serialize());
assert_eq!(sk_bytes, [0; 32]);
}

View File

@ -13,7 +13,7 @@ categories = ["network-programming", "asynchronous"]
[dependencies]
libp2p-swarm = { version = "0.42.1", path = "../../swarm" }
libp2p-core = { version = "0.39.0", path = "../../core" }
libp2p-identity = { version = "0.1.0", path = "../../identity" }
libp2p-identity = { version = "0.1.2", path = "../../identity" }
bytes = "1.4"
byteorder = "1.3.4"
fnv = "1.0.7"

View File

@ -203,7 +203,7 @@ impl From<MessageAuthenticity> for PublishConfig {
match authenticity {
MessageAuthenticity::Signed(keypair) => {
let public_key = keypair.public();
let key_enc = public_key.to_protobuf_encoding();
let key_enc = public_key.encode_protobuf();
let key = if key_enc.len() <= 42 {
// The public key can be inlined in [`rpc_proto::proto::::Message::from`], so we don't include it
// specifically in the [`rpc_proto::proto::Message::key`] field.

View File

@ -234,13 +234,9 @@ impl GossipsubCodec {
// If there is a key value in the protobuf, use that key otherwise the key must be
// obtained from the inlined source peer_id.
let public_key = match message
.key
.as_deref()
.map(PublicKey::from_protobuf_encoding)
{
let public_key = match message.key.as_deref().map(PublicKey::try_decode_protobuf) {
Some(Ok(key)) => key,
_ => match PublicKey::from_protobuf_encoding(&source.to_bytes()[2..]) {
_ => match PublicKey::try_decode_protobuf(&source.to_bytes()[2..]) {
Ok(v) => v,
Err(_) => {
warn!("Signature verification failed: No valid public key supplied");

View File

@ -16,7 +16,7 @@ futures = "0.3.28"
futures-timer = "3.0.2"
libp2p-core = { version = "0.39.0", path = "../../core" }
libp2p-swarm = { version = "0.42.1", path = "../../swarm" }
libp2p-identity = { version = "0.1.0", path = "../../identity" }
libp2p-identity = { version = "0.1.2", path = "../../identity" }
log = "0.4.1"
lru = "0.10.0"
quick-protobuf-codec = { version = "0.1", path = "../../misc/quick-protobuf-codec" }

View File

@ -169,7 +169,7 @@ where
.map(|addr| addr.to_vec())
.collect();
let pubkey_bytes = info.public_key.to_protobuf_encoding();
let pubkey_bytes = info.public_key.encode_protobuf();
let message = proto::Identify {
agentVersion: Some(info.agent_version),
@ -235,7 +235,7 @@ impl TryFrom<proto::Identify> for Info {
addrs
};
let public_key = PublicKey::from_protobuf_encoding(&msg.publicKey.unwrap_or_default())?;
let public_key = PublicKey::try_decode_protobuf(&msg.publicKey.unwrap_or_default())?;
let observed_addr = match parse_multiaddr(msg.observedAddr.unwrap_or_default()) {
Ok(a) => a,
@ -386,7 +386,7 @@ mod tests {
publicKey: Some(
identity::Keypair::generate_ed25519()
.public()
.to_protobuf_encoding(),
.encode_protobuf(),
),
};

View File

@ -13,7 +13,7 @@ bytes = "1"
curve25519-dalek = "3.0.0"
futures = "0.3.28"
libp2p-core = { version = "0.39.0", path = "../../core" }
libp2p-identity = { version = "0.1.0", path = "../../identity", features = ["ed25519"] }
libp2p-identity = { version = "0.1.2", path = "../../identity", features = ["ed25519"] }
log = "0.4"
quick-protobuf = "0.8"
once_cell = "1.17.1"

View File

@ -214,7 +214,7 @@ where
let pb = pb_result?;
if !pb.identity_key.is_empty() {
let pk = identity::PublicKey::from_protobuf_encoding(&pb.identity_key)?;
let pk = identity::PublicKey::try_decode_protobuf(&pb.identity_key)?;
if let Some(ref k) = state.id_remote_pubkey {
if k != &pk {
return Err(NoiseError::UnexpectedKey);
@ -236,7 +236,7 @@ where
T: AsyncWrite + Unpin,
{
let mut pb = proto::NoiseHandshakePayload {
identity_key: state.identity.public.to_protobuf_encoding(),
identity_key: state.identity.public.encode_protobuf(),
..Default::default()
};

View File

@ -15,7 +15,7 @@ asynchronous-codec = "0.6"
bytes = "1"
futures = "0.3.28"
libp2p-core = { version = "0.39.0", path = "../../core" }
libp2p-identity = { version = "0.1.0", path = "../../identity" }
libp2p-identity = { version = "0.1.2", path = "../../identity" }
log = "0.4.8"
quick-protobuf = "0.8"
unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] }

View File

@ -54,7 +54,7 @@ impl HandshakeContext<Local> {
fn new(config: PlainText2Config) -> Self {
let exchange = Exchange {
id: Some(config.local_public_key.to_peer_id().to_bytes()),
pubkey: Some(config.local_public_key.to_protobuf_encoding()),
pubkey: Some(config.local_public_key.encode_protobuf()),
};
let mut buf = Vec::with_capacity(exchange.get_size());
let mut writer = Writer::new(&mut buf);
@ -77,7 +77,7 @@ impl HandshakeContext<Local> {
let mut reader = BytesReader::from_bytes(&exchange_bytes);
let prop = Exchange::from_reader(&mut reader, &exchange_bytes)?;
let public_key = PublicKey::from_protobuf_encoding(&prop.pubkey.unwrap_or_default())?;
let public_key = PublicKey::try_decode_protobuf(&prop.pubkey.unwrap_or_default())?;
let peer_id = PeerId::from_bytes(&prop.id.unwrap_or_default())?;
// Check the validity of the remote's `Exchange`.

View File

@ -12,7 +12,7 @@ exclude = ["src/test_assets"]
futures = { version = "0.3.28", default-features = false }
futures-rustls = "0.22.2"
libp2p-core = { version = "0.39.0", path = "../../core" }
libp2p-identity = { version = "0.1.0", path = "../../identity" }
libp2p-identity = { version = "0.1.2", path = "../../identity" }
rcgen = "0.10.0"
ring = "0.16.20"
thiserror = "1.0.40"

View File

@ -159,7 +159,7 @@ fn parse_unverified(der_input: &[u8]) -> Result<P2pCertificate, webpki::Error> {
// required KeyType Type = 1;
// required bytes Data = 2;
// }
let public_key = identity::PublicKey::from_protobuf_encoding(&public_key)
let public_key = identity::PublicKey::try_decode_protobuf(&public_key)
.map_err(|_| webpki::Error::UnknownIssuer)?;
let ext = P2pExtension {
public_key,
@ -215,7 +215,7 @@ fn make_libp2p_extension(
// signature OCTET STRING
// }
let extension_content = {
let serialized_pubkey = identity_keypair.public().to_protobuf_encoding();
let serialized_pubkey = identity_keypair.public().encode_protobuf();
yasna::encode_der(&(serialized_pubkey, signature))
};