pub mod ed25519;
#[cfg(not(target_arch = "wasm32"))]
pub mod rsa;
#[cfg(feature = "secp256k1")]
pub mod secp256k1;
use crate::{pb::key_pair_proto, peer_id::PeerId, Error, Result};
pub enum Keypair {
Ed25519(ed25519::Keypair),
#[cfg(not(target_arch = "wasm32"))]
Rsa(rsa::Keypair),
#[cfg(feature = "secp256k1")]
Secp256k1(secp256k1::Keypair),
}
impl Keypair {
pub fn generate_ed25519() -> Result<Keypair> {
Ok(Keypair::Ed25519(ed25519::Keypair::generate()?))
}
#[cfg(feature = "secp256k1")]
pub fn generate_secp256k1() -> Result<Keypair> {
Ok(Keypair::Secp256k1(secp256k1::Keypair::generate()))
}
#[cfg(not(target_arch = "wasm32"))]
pub fn from_rsa_pkcs8(pkcs8_der: &mut [u8]) -> Result<Keypair> {
rsa::Keypair::from_pkcs8(pkcs8_der).map(Keypair::Rsa)
}
pub fn from_ed25519_bytes(data: &mut [u8]) -> Result<Keypair> {
ed25519::Keypair::decode(data).map(Keypair::Ed25519)
}
#[cfg(feature = "secp256k1")]
pub fn from_secp256k1_der(der: &mut [u8]) -> Result<Keypair> {
let secret_key = secp256k1::SecretKey::from_der(der)?;
Ok(Keypair::Secp256k1(secp256k1::Keypair::from(secret_key)))
}
}
impl Keypair {
pub fn to_public_key(&self) -> PublicKey {
use Keypair::*;
match self {
Ed25519(pair) => PublicKey::Ed25519(pair.to_public_key()),
#[cfg(not(target_arch = "wasm32"))]
Rsa(pair) => PublicKey::Rsa(pair.to_public_key()),
#[cfg(feature = "secp256k1")]
Secp256k1(pair) => PublicKey::Secp256k1(pair.to_public_key().clone()),
}
}
pub fn sign(&self, msg: &[u8]) -> Result<Vec<u8>> {
use Keypair::*;
match self {
Ed25519(ref pair) => pair.sign(msg),
#[cfg(not(target_arch = "wasm32"))]
Rsa(ref pair) => pair.sign(msg),
#[cfg(feature = "secp256k1")]
Secp256k1(ref pair) => pair.as_secret_key().sign(msg),
}
}
pub fn try_clone(&self) -> Result<Self> {
use Keypair::*;
match self {
Ed25519(ref pair) => pair.try_clone().map(Ed25519),
#[cfg(not(target_arch = "wasm32"))]
Rsa(ref pair) => Ok(pair.clone()).map(Rsa),
#[cfg(feature = "secp256k1")]
Secp256k1(ref pair) => Ok(pair.clone()).map(Secp256k1),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum PublicKey {
Ed25519(ed25519::PublicKey),
#[cfg(not(target_arch = "wasm32"))]
Rsa(rsa::PublicKey),
#[cfg(feature = "secp256k1")]
Secp256k1(secp256k1::PublicKey),
}
impl PublicKey {
pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
use PublicKey::*;
match self {
Ed25519(pk) => pk.verify(msg, sig),
#[cfg(not(target_arch = "wasm32"))]
Rsa(pk) => pk.verify(msg, sig),
#[cfg(feature = "secp256k1")]
Secp256k1(pk) => pk.verify(msg, sig),
}
}
pub fn into_protobuf_encoding(self) -> Result<Vec<u8>> {
use prost::Message;
let public_key = match self {
PublicKey::Ed25519(key) => key_pair_proto::PublicKey {
r#type: key_pair_proto::KeyType::Ed25519 as i32,
data: key.encode().to_vec(),
},
#[cfg(not(target_arch = "wasm32"))]
PublicKey::Rsa(key) => key_pair_proto::PublicKey {
r#type: key_pair_proto::KeyType::Rsa as i32,
data: key.encode_x509()?,
},
#[cfg(feature = "secp256k1")]
PublicKey::Secp256k1(key) => key_pair_proto::PublicKey {
r#type: key_pair_proto::KeyType::Secp256k1 as i32,
data: key.encode().to_vec(),
},
};
let mut buf = Vec::with_capacity(public_key.encoded_len());
err_at!(EncodeError, public_key.encode(&mut buf))?;
Ok(buf)
}
pub fn from_protobuf_encoding(bytes: &[u8]) -> Result<PublicKey> {
use prost::Message;
#[allow(unused_mut)] let mut pubkey = {
let res = key_pair_proto::PublicKey::decode(bytes);
err_at!(DecodeError, res)?
};
let key_type = match key_pair_proto::KeyType::from_i32(pubkey.r#type) {
Some(typ) => Ok(typ),
None => {
let msg = format!("unknown key type: {}", pubkey.r#type);
err_at!(DecodeError, msg: msg)
}
}?;
match key_type {
key_pair_proto::KeyType::Ed25519 => {
ed25519::PublicKey::decode(&pubkey.data).map(PublicKey::Ed25519)
}
#[cfg(not(target_arch = "wasm32"))]
key_pair_proto::KeyType::Rsa => {
rsa::PublicKey::decode_x509(&pubkey.data).map(PublicKey::Rsa)
}
#[cfg(target_arch = "wasm32")]
key_pair_proto::KeyType::Rsa => {
let msg = format!("RSA disabled at compile-time");
err_at!(DecodeError, msg: msg)
}
#[cfg(feature = "secp256k1")]
key_pair_proto::KeyType::Secp256k1 => {
secp256k1::PublicKey::decode(&pubkey.data).map(PublicKey::Secp256k1)
}
#[cfg(not(feature = "secp256k1"))]
key_pair_proto::KeyType::Secp256k1 => {
let msg = format!("secp256k1 disabled at compile-time");
err_at!(DecodeError, msg: msg)
}
}
}
pub fn into_peer_id(self) -> Result<PeerId> {
PeerId::from_public_key(self)
}
}
#[cfg(test)]
mod tests {
#[test]
fn print_keys_proto_path() {
let file_path = concat!(env!("OUT_DIR"), "/key_pair_proto.rs");
println!(".... key_pair_proto file: {}", file_path);
}
}
#[cfg(test)]
#[path = "identity_test.rs"]
mod identity_test;