2023-03-13 01:46:58 +11:00
|
|
|
// Copyright 2023 Protocol Labs.
|
2019-03-11 13:42:53 +01:00
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
|
|
// to deal in the Software without restriction, including without limitation
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
2023-04-14 16:55:13 +08:00
|
|
|
use crate::error::OtherVariantError;
|
2023-03-13 01:46:58 +11:00
|
|
|
use crate::error::{DecodingError, SigningError};
|
2023-05-01 16:10:37 +02:00
|
|
|
use crate::proto;
|
2023-03-13 01:46:58 +11:00
|
|
|
use quick_protobuf::{BytesReader, Writer};
|
|
|
|
use std::convert::TryFrom;
|
|
|
|
|
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
use crate::ed25519;
|
2019-03-11 13:42:53 +01:00
|
|
|
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-03-13 01:46:58 +11:00
|
|
|
use crate::rsa;
|
2019-03-11 13:42:53 +01:00
|
|
|
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
use crate::secp256k1;
|
2019-03-11 13:42:53 +01:00
|
|
|
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
use crate::ecdsa;
|
2019-03-11 13:42:53 +01:00
|
|
|
|
|
|
|
/// Identity keypair of a node.
|
|
|
|
///
|
|
|
|
/// # Example: Generating RSA keys with OpenSSL
|
|
|
|
///
|
|
|
|
/// ```text
|
|
|
|
/// openssl genrsa -out private.pem 2048
|
|
|
|
/// openssl pkcs8 -in private.pem -inform PEM -topk8 -out private.pk8 -outform DER -nocrypt
|
|
|
|
/// rm private.pem # optional
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Loading the keys:
|
|
|
|
///
|
|
|
|
/// ```text
|
2020-09-17 20:50:58 +02:00
|
|
|
/// let mut bytes = std::fs::read("private.pk8").unwrap();
|
2019-03-11 13:42:53 +01:00
|
|
|
/// let keypair = Keypair::rsa_from_pkcs8(&mut bytes);
|
|
|
|
/// ```
|
|
|
|
///
|
2022-02-16 17:16:54 +02:00
|
|
|
#[derive(Debug, Clone)]
|
2022-08-19 05:06:55 +02:00
|
|
|
#[allow(clippy::large_enum_variant)]
|
2019-03-11 13:42:53 +01:00
|
|
|
pub enum Keypair {
|
|
|
|
/// An Ed25519 keypair.
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-14 16:55:13 +08:00
|
|
|
note = "This enum will be made opaque in the future, use `Keypair::try_into_ed25519` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2019-03-11 13:42:53 +01:00
|
|
|
Ed25519(ed25519::Keypair),
|
|
|
|
/// An RSA keypair.
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-03-13 01:46:58 +11:00
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-14 16:55:13 +08:00
|
|
|
note = "This enum will be made opaque in the future, use `Keypair::try_into_rsa` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2019-03-11 13:42:53 +01:00
|
|
|
Rsa(rsa::Keypair),
|
|
|
|
/// A Secp256k1 keypair.
|
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-03-13 01:46:58 +11:00
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-14 16:55:13 +08:00
|
|
|
note = "This enum will be made opaque in the future, use `Keypair::try_into_secp256k1` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2021-08-11 13:12:12 +02:00
|
|
|
Secp256k1(secp256k1::Keypair),
|
2021-11-30 17:47:35 +01:00
|
|
|
/// An ECDSA keypair.
|
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-03-13 01:46:58 +11:00
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-14 16:55:13 +08:00
|
|
|
note = "This enum will be made opaque in the future, use `Keypair::try_into_ecdsa` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2021-11-30 17:47:35 +01:00
|
|
|
Ecdsa(ecdsa::Keypair),
|
2019-03-11 13:42:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Keypair {
|
|
|
|
/// Generate a new Ed25519 keypair.
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2019-03-11 13:42:53 +01:00
|
|
|
pub fn generate_ed25519() -> Keypair {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2019-03-11 13:42:53 +01:00
|
|
|
Keypair::Ed25519(ed25519::Keypair::generate())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Generate a new Secp256k1 keypair.
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
pub fn generate_secp256k1() -> Keypair {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2019-03-11 13:42:53 +01:00
|
|
|
Keypair::Secp256k1(secp256k1::Keypair::generate())
|
|
|
|
}
|
|
|
|
|
2021-11-30 17:47:35 +01:00
|
|
|
/// Generate a new ECDSA keypair.
|
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
pub fn generate_ecdsa() -> Keypair {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2021-11-30 17:47:35 +01:00
|
|
|
Keypair::Ecdsa(ecdsa::Keypair::generate())
|
|
|
|
}
|
|
|
|
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_ed25519` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_ed25519(self) -> Option<ed25519::Keypair> {
|
2023-04-14 16:55:13 +08:00
|
|
|
self.try_into().ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
pub fn try_into_ed25519(self) -> Result<ed25519::Keypair, OtherVariantError> {
|
|
|
|
self.try_into()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_secp256k1` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_secp256k1(self) -> Option<secp256k1::Keypair> {
|
2023-04-14 16:55:13 +08:00
|
|
|
self.try_into().ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
pub fn try_into_secp256k1(self) -> Result<secp256k1::Keypair, OtherVariantError> {
|
|
|
|
self.try_into()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_rsa` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_rsa(self) -> Option<rsa::Keypair> {
|
2023-04-14 16:55:13 +08:00
|
|
|
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()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `Keypair::try_into_ecdsa` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_ecdsa(self) -> Option<ecdsa::Keypair> {
|
2023-04-14 16:55:13 +08:00
|
|
|
self.try_into().ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
pub fn try_into_ecdsa(self) -> Result<ecdsa::Keypair, OtherVariantError> {
|
|
|
|
self.try_into()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
/// Decode an keypair from a DER-encoded secret key in PKCS#8 PrivateKeyInfo
|
|
|
|
/// format (i.e. unencrypted) as defined in [RFC5208].
|
|
|
|
///
|
|
|
|
/// [RFC5208]: https://tools.ietf.org/html/rfc5208#section-5
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2019-03-11 13:42:53 +01:00
|
|
|
pub fn rsa_from_pkcs8(pkcs8_der: &mut [u8]) -> Result<Keypair, DecodingError> {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2019-03-11 13:42:53 +01:00
|
|
|
rsa::Keypair::from_pkcs8(pkcs8_der).map(Keypair::Rsa)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Decode a keypair from a DER-encoded Secp256k1 secret key in an ECPrivateKey
|
|
|
|
/// structure as defined in [RFC5915].
|
|
|
|
///
|
|
|
|
/// [RFC5915]: https://tools.ietf.org/html/rfc5915
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
pub fn secp256k1_from_der(der: &mut [u8]) -> Result<Keypair, DecodingError> {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2019-03-11 13:42:53 +01:00
|
|
|
secp256k1::SecretKey::from_der(der)
|
|
|
|
.map(|sk| Keypair::Secp256k1(secp256k1::Keypair::from(sk)))
|
|
|
|
}
|
|
|
|
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
pub fn ed25519_from_bytes(bytes: impl AsMut<[u8]>) -> Result<Keypair, DecodingError> {
|
|
|
|
#[allow(deprecated)]
|
|
|
|
Ok(Keypair::Ed25519(ed25519::Keypair::from(
|
|
|
|
ed25519::SecretKey::from_bytes(bytes)?,
|
|
|
|
)))
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
/// Sign a message using the private key of this keypair, producing
|
|
|
|
/// a signature that can be verified using the corresponding public key.
|
|
|
|
pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
|
|
|
|
use Keypair::*;
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2019-03-11 13:42:53 +01:00
|
|
|
match self {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2019-03-11 13:42:53 +01:00
|
|
|
Ed25519(ref pair) => Ok(pair.sign(msg)),
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2019-03-11 13:42:53 +01:00
|
|
|
Rsa(ref pair) => pair.sign(msg),
|
|
|
|
#[cfg(feature = "secp256k1")]
|
2021-08-11 13:12:12 +02:00
|
|
|
Secp256k1(ref pair) => pair.secret().sign(msg),
|
2021-11-30 17:47:35 +01:00
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
Ecdsa(ref pair) => Ok(pair.secret().sign(msg)),
|
2019-03-11 13:42:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the public key of this keypair.
|
|
|
|
pub fn public(&self) -> PublicKey {
|
|
|
|
use Keypair::*;
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2019-03-11 13:42:53 +01:00
|
|
|
match self {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2019-03-11 13:42:53 +01:00
|
|
|
Ed25519(pair) => PublicKey::Ed25519(pair.public()),
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2019-03-11 13:42:53 +01:00
|
|
|
Rsa(pair) => PublicKey::Rsa(pair.public()),
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
Secp256k1(pair) => PublicKey::Secp256k1(pair.public().clone()),
|
2021-11-30 17:47:35 +01:00
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
Ecdsa(pair) => PublicKey::Ecdsa(pair.public().clone()),
|
2019-03-11 13:42:53 +01:00
|
|
|
}
|
|
|
|
}
|
2021-06-07 10:17:46 +02:00
|
|
|
|
2021-07-28 17:59:08 +02:00
|
|
|
/// Encode a private key as protobuf structure.
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg_attr(
|
|
|
|
not(feature = "ed25519"),
|
|
|
|
allow(unreachable_code, unused_variables, unused_mut)
|
|
|
|
)]
|
2021-07-28 17:59:08 +02:00
|
|
|
pub fn to_protobuf_encoding(&self) -> Result<Vec<u8>, DecodingError> {
|
2023-03-02 05:45:07 -05:00
|
|
|
use quick_protobuf::MessageWrite;
|
2021-07-28 17:59:08 +02:00
|
|
|
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(not(feature = "ed25519"))]
|
|
|
|
return Err(DecodingError::missing_feature("ed25519"));
|
|
|
|
|
|
|
|
#[allow(deprecated)]
|
|
|
|
let pk: proto::PrivateKey = match self {
|
|
|
|
#[cfg(feature = "ed25519")]
|
2023-03-02 05:45:07 -05:00
|
|
|
Self::Ed25519(data) => proto::PrivateKey {
|
|
|
|
Type: proto::KeyType::Ed25519,
|
|
|
|
Data: data.encode().to_vec(),
|
2021-07-28 17:59:08 +02:00
|
|
|
},
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2022-11-23 11:51:47 +11:00
|
|
|
Self::Rsa(_) => return Err(DecodingError::encoding_unsupported("RSA")),
|
2021-07-28 17:59:08 +02:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2022-11-23 11:51:47 +11:00
|
|
|
Self::Secp256k1(_) => return Err(DecodingError::encoding_unsupported("secp256k1")),
|
2021-11-30 17:47:35 +01:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2022-11-23 11:51:47 +11:00
|
|
|
Self::Ecdsa(_) => return Err(DecodingError::encoding_unsupported("ECDSA")),
|
2021-07-28 17:59:08 +02:00
|
|
|
};
|
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
let mut buf = Vec::with_capacity(pk.get_size());
|
|
|
|
let mut writer = Writer::new(&mut buf);
|
|
|
|
pk.write_message(&mut writer).expect("Encoding to succeed");
|
|
|
|
|
|
|
|
Ok(buf)
|
2021-07-28 17:59:08 +02:00
|
|
|
}
|
|
|
|
|
2021-06-07 10:17:46 +02:00
|
|
|
/// Decode a private key from a protobuf structure and parse it as a [`Keypair`].
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg_attr(not(feature = "ed25519"), allow(unused_mut))]
|
2021-06-07 10:17:46 +02:00
|
|
|
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<Keypair, DecodingError> {
|
2023-03-02 05:45:07 -05:00
|
|
|
use quick_protobuf::MessageRead;
|
2021-06-07 10:17:46 +02:00
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
let mut reader = BytesReader::from_bytes(bytes);
|
|
|
|
let mut private_key = proto::PrivateKey::from_reader(&mut reader, bytes)
|
2022-11-23 11:51:47 +11:00
|
|
|
.map_err(|e| DecodingError::bad_protobuf("private key bytes", e))
|
2021-06-07 10:17:46 +02:00
|
|
|
.map(zeroize::Zeroizing::new)?;
|
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
match private_key.Type {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
proto::KeyType::Ed25519 =>
|
|
|
|
{
|
|
|
|
#[allow(deprecated)]
|
2023-03-02 05:45:07 -05:00
|
|
|
ed25519::Keypair::decode(&mut private_key.Data).map(Keypair::Ed25519)
|
2021-08-11 13:12:12 +02:00
|
|
|
}
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(not(feature = "ed25519"))]
|
|
|
|
proto::KeyType::Ed25519 => Err(DecodingError::missing_feature("ed25519")),
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::RSA => Err(DecodingError::decoding_unsupported("RSA")),
|
|
|
|
proto::KeyType::Secp256k1 => Err(DecodingError::decoding_unsupported("secp256k1")),
|
|
|
|
proto::KeyType::ECDSA => Err(DecodingError::decoding_unsupported("ECDSA")),
|
2021-06-07 10:17:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-16 21:40:54 +05:30
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
impl From<ecdsa::Keypair> for Keypair {
|
|
|
|
fn from(kp: ecdsa::Keypair) -> Self {
|
|
|
|
#[allow(deprecated)]
|
|
|
|
Keypair::Ecdsa(kp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
impl From<ed25519::Keypair> for Keypair {
|
|
|
|
fn from(kp: ed25519::Keypair) -> Self {
|
|
|
|
#[allow(deprecated)]
|
|
|
|
Keypair::Ed25519(kp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
impl From<secp256k1::Keypair> for Keypair {
|
|
|
|
fn from(kp: secp256k1::Keypair) -> Self {
|
|
|
|
#[allow(deprecated)]
|
|
|
|
Keypair::Secp256k1(kp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
|
|
|
impl From<rsa::Keypair> for Keypair {
|
|
|
|
fn from(kp: rsa::Keypair) -> Self {
|
|
|
|
#[allow(deprecated)]
|
|
|
|
Keypair::Rsa(kp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-14 16:55:13 +08:00
|
|
|
#[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")))]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-05-01 16:10:37 +02:00
|
|
|
Keypair::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
/// The public key of a node's identity keypair.
|
2022-09-22 21:35:42 +04:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
2019-03-11 13:42:53 +01:00
|
|
|
pub enum PublicKey {
|
|
|
|
/// A public Ed25519 key.
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-22 07:16:58 -03:00
|
|
|
note = "This enum will be made opaque in the future, use `PublicKey::from` and `PublicKey::into_ed25519` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2019-03-11 13:42:53 +01:00
|
|
|
Ed25519(ed25519::PublicKey),
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2019-03-11 13:42:53 +01:00
|
|
|
/// A public RSA key.
|
2023-03-13 01:46:58 +11:00
|
|
|
|
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-22 07:16:58 -03:00
|
|
|
note = "This enum will be made opaque in the future, use `PublicKey::from` and `PublicKey::into_rsa` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2019-03-11 13:42:53 +01:00
|
|
|
Rsa(rsa::PublicKey),
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
/// A public Secp256k1 key.
|
2023-03-13 01:46:58 +11:00
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-22 07:16:58 -03:00
|
|
|
note = "This enum will be made opaque in the future, use `PublicKey::from` and `PublicKey::into_secp256k1` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2021-08-11 13:12:12 +02:00
|
|
|
Secp256k1(secp256k1::PublicKey),
|
2021-11-30 17:47:35 +01:00
|
|
|
/// A public ECDSA key.
|
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-03-13 01:46:58 +11:00
|
|
|
#[deprecated(
|
|
|
|
since = "0.1.0",
|
2023-04-22 07:16:58 -03:00
|
|
|
note = "This enum will be made opaque in the future, use `PublicKey::from` and `PublicKey::into_ecdsa` instead."
|
2023-03-13 01:46:58 +11:00
|
|
|
)]
|
2021-11-30 17:47:35 +01:00
|
|
|
Ecdsa(ecdsa::PublicKey),
|
2019-03-11 13:42:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PublicKey {
|
|
|
|
/// Verify a signature for a message using this public key, i.e. check
|
|
|
|
/// that the signature has been produced by the corresponding
|
|
|
|
/// private key (authenticity), and that the message has not been
|
|
|
|
/// tampered with (integrity).
|
2021-09-08 00:36:52 +10:00
|
|
|
#[must_use]
|
2019-03-11 13:42:53 +01:00
|
|
|
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
|
|
|
|
use PublicKey::*;
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2019-03-11 13:42:53 +01:00
|
|
|
match self {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2019-03-11 13:42:53 +01:00
|
|
|
Ed25519(pk) => pk.verify(msg, sig),
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2019-03-11 13:42:53 +01:00
|
|
|
Rsa(pk) => pk.verify(msg, sig),
|
|
|
|
#[cfg(feature = "secp256k1")]
|
2021-08-11 13:12:12 +02:00
|
|
|
Secp256k1(pk) => pk.verify(msg, sig),
|
2021-11-30 17:47:35 +01:00
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
Ecdsa(pk) => pk.verify(msg, sig),
|
2019-03-11 13:42:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_ed25519` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_ed25519(self) -> Option<ed25519::PublicKey> {
|
2023-04-14 16:55:13 +08:00
|
|
|
self.try_into().ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
pub fn try_into_ed25519(self) -> Result<ed25519::PublicKey, OtherVariantError> {
|
|
|
|
self.try_into()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_secp256k1` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_secp256k1(self) -> Option<secp256k1::PublicKey> {
|
2023-04-14 16:55:13 +08:00
|
|
|
self.try_into().ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
pub fn try_into_secp256k1(self) -> Result<secp256k1::PublicKey, OtherVariantError> {
|
|
|
|
self.try_into()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_rsa` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_rsa(self) -> Option<rsa::PublicKey> {
|
2023-04-14 16:55:13 +08:00
|
|
|
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()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_into_ecdsa` instead."
|
|
|
|
)]
|
2023-03-13 01:46:58 +11:00
|
|
|
pub fn into_ecdsa(self) -> Option<ecdsa::PublicKey> {
|
2023-04-14 16:55:13 +08:00
|
|
|
self.try_into().ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
pub fn try_into_ecdsa(self) -> Result<ecdsa::PublicKey, OtherVariantError> {
|
|
|
|
self.try_into()
|
2023-03-13 01:46:58 +11:00
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
/// Encode the public key into a protobuf structure for storage or
|
|
|
|
/// exchange with other nodes.
|
2023-04-22 07:16:58 -03:00
|
|
|
#[deprecated(note = "Renamed to `PublicKey::encode_protobuf`.")]
|
2021-07-22 22:34:13 +02:00
|
|
|
pub fn to_protobuf_encoding(&self) -> Vec<u8> {
|
2023-04-14 16:55:13 +08:00
|
|
|
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> {
|
2023-03-02 05:45:07 -05:00
|
|
|
use quick_protobuf::MessageWrite;
|
2020-01-15 12:02:02 +01:00
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
let public_key = proto::PublicKey::from(self);
|
2021-09-08 00:36:52 +10:00
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
let mut buf = Vec::with_capacity(public_key.get_size());
|
|
|
|
let mut writer = Writer::new(&mut buf);
|
2021-09-08 00:36:52 +10:00
|
|
|
public_key
|
2023-03-02 05:45:07 -05:00
|
|
|
.write_message(&mut writer)
|
|
|
|
.expect("Encoding to succeed");
|
|
|
|
|
2021-09-08 00:36:52 +10:00
|
|
|
buf
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Decode a public key from a protobuf structure, e.g. read from storage
|
|
|
|
/// or received from another node.
|
2023-04-14 16:55:13 +08:00
|
|
|
#[deprecated(
|
|
|
|
note = "This method name does not follow Rust naming conventions, use `PublicKey::try_decode_protobuf` instead."
|
|
|
|
)]
|
2021-09-08 00:36:52 +10:00
|
|
|
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
|
2023-04-14 16:55:13 +08:00
|
|
|
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> {
|
2023-03-02 05:45:07 -05:00
|
|
|
use quick_protobuf::MessageRead;
|
2021-09-08 00:36:52 +10:00
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
let mut reader = BytesReader::from_bytes(bytes);
|
|
|
|
|
|
|
|
let pubkey = proto::PublicKey::from_reader(&mut reader, bytes)
|
2022-11-23 11:51:47 +11:00
|
|
|
.map_err(|e| DecodingError::bad_protobuf("public key bytes", e))?;
|
2021-09-08 00:36:52 +10:00
|
|
|
|
|
|
|
pubkey.try_into()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Convert the `PublicKey` into the corresponding `PeerId`.
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "peerid")]
|
|
|
|
pub fn to_peer_id(&self) -> crate::PeerId {
|
2021-09-08 00:36:52 +10:00
|
|
|
self.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
impl TryFrom<proto::PublicKey> for PublicKey {
|
2021-09-08 00:36:52 +10:00
|
|
|
type Error = DecodingError;
|
2019-03-11 13:42:53 +01:00
|
|
|
|
2023-03-02 05:45:07 -05:00
|
|
|
fn try_from(pubkey: proto::PublicKey) -> Result<Self, Self::Error> {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[allow(deprecated)]
|
2023-03-02 05:45:07 -05:00
|
|
|
match pubkey.Type {
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::Ed25519 => {
|
|
|
|
ed25519::PublicKey::decode(&pubkey.Data).map(PublicKey::Ed25519)
|
2021-08-11 13:12:12 +02:00
|
|
|
}
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(not(feature = "ed25519"))]
|
|
|
|
proto::KeyType::Ed25519 => {
|
|
|
|
log::debug!("support for ed25519 was disabled at compile-time");
|
|
|
|
Err(DecodingError::missing_feature("ed25519"))
|
|
|
|
}
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::RSA => rsa::PublicKey::decode_x509(&pubkey.Data).map(PublicKey::Rsa),
|
2022-09-07 09:16:22 +03:00
|
|
|
#[cfg(any(not(feature = "rsa"), target_arch = "wasm32"))]
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::RSA => {
|
2019-03-11 13:42:53 +01:00
|
|
|
log::debug!("support for RSA was disabled at compile-time");
|
2022-11-23 11:51:47 +11:00
|
|
|
Err(DecodingError::missing_feature("rsa"))
|
2021-08-11 13:12:12 +02:00
|
|
|
}
|
2019-03-11 13:42:53 +01:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::Secp256k1 => {
|
|
|
|
secp256k1::PublicKey::decode(&pubkey.Data).map(PublicKey::Secp256k1)
|
2019-03-11 13:42:53 +01:00
|
|
|
}
|
|
|
|
#[cfg(not(feature = "secp256k1"))]
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::Secp256k1 => {
|
2019-03-11 13:42:53 +01:00
|
|
|
log::debug!("support for secp256k1 was disabled at compile-time");
|
2022-11-23 11:51:47 +11:00
|
|
|
Err(DecodingError::missing_feature("secp256k1"))
|
2020-01-15 12:02:02 +01:00
|
|
|
}
|
2021-11-30 17:47:35 +01:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::ECDSA => {
|
|
|
|
ecdsa::PublicKey::decode_der(&pubkey.Data).map(PublicKey::Ecdsa)
|
2021-11-30 17:47:35 +01:00
|
|
|
}
|
|
|
|
#[cfg(not(feature = "ecdsa"))]
|
2023-03-02 05:45:07 -05:00
|
|
|
proto::KeyType::ECDSA => {
|
2021-11-30 17:47:35 +01:00
|
|
|
log::debug!("support for ECDSA was disabled at compile-time");
|
2022-11-23 11:51:47 +11:00
|
|
|
Err(DecodingError::missing_feature("ecdsa"))
|
2021-11-30 17:47:35 +01:00
|
|
|
}
|
2019-03-11 13:42:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-14 16:55:13 +08:00
|
|
|
#[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")))]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Rsa(_) => Err(OtherVariantError::new(crate::KeyType::RSA)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Ed25519(_) => Err(OtherVariantError::new(crate::KeyType::Ed25519)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "secp256k1")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Secp256k1(_) => Err(OtherVariantError::new(crate::KeyType::Secp256k1)),
|
2023-04-14 16:55:13 +08:00
|
|
|
#[cfg(feature = "ecdsa")]
|
2023-05-01 16:10:37 +02:00
|
|
|
PublicKey::Ecdsa(_) => Err(OtherVariantError::new(crate::KeyType::Ecdsa)),
|
2023-04-14 16:55:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-22 07:16:58 -03:00
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
impl From<ed25519::PublicKey> for PublicKey {
|
|
|
|
fn from(key: ed25519::PublicKey) -> Self {
|
|
|
|
#[allow(deprecated)] // TODO: Remove when PublicKey::Ed25519 is made opaque
|
|
|
|
PublicKey::Ed25519(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
impl From<secp256k1::PublicKey> for PublicKey {
|
|
|
|
fn from(key: secp256k1::PublicKey) -> Self {
|
|
|
|
#[allow(deprecated)] // TODO: Remove when PublicKey::Secp256k1 is made opaque
|
|
|
|
PublicKey::Secp256k1(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
impl From<ecdsa::PublicKey> for PublicKey {
|
|
|
|
fn from(key: ecdsa::PublicKey) -> Self {
|
|
|
|
#[allow(deprecated)] // TODO: Remove when PublicKey::Ecdsa is made opaque
|
|
|
|
PublicKey::Ecdsa(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
|
|
|
|
impl From<rsa::PublicKey> for PublicKey {
|
|
|
|
fn from(key: rsa::PublicKey) -> Self {
|
|
|
|
#[allow(deprecated)] // TODO: Remove when PublicKey::Rsa is made opaque
|
|
|
|
PublicKey::Rsa(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-07 10:17:46 +02:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2023-04-22 07:16:58 -03:00
|
|
|
#[cfg(feature = "peerid")]
|
2023-03-13 01:46:58 +11:00
|
|
|
use crate::PeerId;
|
2023-02-24 00:36:59 +00:00
|
|
|
use base64::prelude::*;
|
2021-06-07 10:17:46 +02:00
|
|
|
use std::str::FromStr;
|
|
|
|
|
2021-07-28 17:59:08 +02:00
|
|
|
#[test]
|
2023-03-13 01:46:58 +11:00
|
|
|
#[cfg(feature = "ed25519")]
|
2023-04-22 07:16:58 -03:00
|
|
|
#[cfg(feature = "peerid")]
|
2021-07-28 17:59:08 +02:00
|
|
|
fn keypair_protobuf_roundtrip() {
|
|
|
|
let expected_keypair = Keypair::generate_ed25519();
|
|
|
|
let expected_peer_id = expected_keypair.public().to_peer_id();
|
|
|
|
|
|
|
|
let encoded = expected_keypair.to_protobuf_encoding().unwrap();
|
|
|
|
|
|
|
|
let keypair = Keypair::from_protobuf_encoding(&encoded).unwrap();
|
|
|
|
let peer_id = keypair.public().to_peer_id();
|
|
|
|
|
|
|
|
assert_eq!(expected_peer_id, peer_id);
|
|
|
|
}
|
|
|
|
|
2021-06-07 10:17:46 +02:00
|
|
|
#[test]
|
2023-04-22 07:16:58 -03:00
|
|
|
#[cfg(feature = "peerid")]
|
2021-06-07 10:17:46 +02:00
|
|
|
fn keypair_from_protobuf_encoding() {
|
|
|
|
// E.g. retrieved from an IPFS config file.
|
|
|
|
let base_64_encoded = "CAESQL6vdKQuznQosTrW7FWI9At+XX7EBf0BnZLhb6w+N+XSQSdfInl6c7U4NuxXJlhKcRBlBw9d0tj2dfBIVf6mcPA=";
|
2021-08-11 13:12:12 +02:00
|
|
|
let expected_peer_id =
|
|
|
|
PeerId::from_str("12D3KooWEChVMMMzV8acJ53mJHrw1pQ27UAGkCxWXLJutbeUMvVu").unwrap();
|
2021-06-07 10:17:46 +02:00
|
|
|
|
2023-02-24 00:36:59 +00:00
|
|
|
let encoded = BASE64_STANDARD.decode(base_64_encoded).unwrap();
|
2021-06-07 10:17:46 +02:00
|
|
|
|
|
|
|
let keypair = Keypair::from_protobuf_encoding(&encoded).unwrap();
|
2021-07-22 22:34:13 +02:00
|
|
|
let peer_id = keypair.public().to_peer_id();
|
2021-06-07 10:17:46 +02:00
|
|
|
|
|
|
|
assert_eq!(expected_peer_id, peer_id);
|
|
|
|
}
|
2022-09-22 21:35:42 +04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn public_key_implements_hash() {
|
2023-03-13 01:46:58 +11:00
|
|
|
use crate::PublicKey;
|
2022-09-22 21:35:42 +04:00
|
|
|
use std::hash::Hash;
|
|
|
|
|
|
|
|
fn assert_implements_hash<T: Hash>() {}
|
|
|
|
|
|
|
|
assert_implements_hash::<PublicKey>();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn public_key_implements_ord() {
|
2023-03-13 01:46:58 +11:00
|
|
|
use crate::PublicKey;
|
2022-09-22 21:35:42 +04:00
|
|
|
use std::cmp::Ord;
|
|
|
|
|
|
|
|
fn assert_implements_ord<T: Ord>() {}
|
|
|
|
|
|
|
|
assert_implements_ord::<PublicKey>();
|
|
|
|
}
|
2023-04-22 07:16:58 -03:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(feature = "ed25519")]
|
|
|
|
fn test_publickey_from_ed25519_public_key() {
|
|
|
|
let pubkey = Keypair::generate_ed25519().public();
|
|
|
|
let ed25519_pubkey = pubkey
|
|
|
|
.clone()
|
|
|
|
.try_into_ed25519()
|
|
|
|
.expect("A ed25519 keypair");
|
|
|
|
|
|
|
|
let converted_pubkey = PublicKey::from(ed25519_pubkey);
|
|
|
|
|
|
|
|
assert_eq!(converted_pubkey, pubkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(feature = "secp256k1")]
|
|
|
|
fn test_publickey_from_secp256k1_public_key() {
|
|
|
|
let pubkey = Keypair::generate_secp256k1().public();
|
|
|
|
let secp256k1_pubkey = pubkey
|
|
|
|
.clone()
|
|
|
|
.try_into_secp256k1()
|
|
|
|
.expect("A secp256k1 keypair");
|
|
|
|
let converted_pubkey = PublicKey::from(secp256k1_pubkey);
|
|
|
|
|
|
|
|
assert_eq!(converted_pubkey, pubkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[cfg(feature = "ecdsa")]
|
|
|
|
fn test_publickey_from_ecdsa_public_key() {
|
|
|
|
let pubkey = Keypair::generate_ecdsa().public();
|
|
|
|
let ecdsa_pubkey = pubkey.clone().try_into_ecdsa().expect("A ecdsa keypair");
|
|
|
|
let converted_pubkey = PublicKey::from(ecdsa_pubkey);
|
|
|
|
|
|
|
|
assert_eq!(converted_pubkey, pubkey);
|
|
|
|
}
|
2021-06-07 10:17:46 +02:00
|
|
|
}
|