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

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]);
}