use super::{ed25519_dalek as ed25519, EnrKey, EnrPublicKey, SigningError};
use crate::Key;
use alloy_rlp::Error as DecoderError;
use bytes::Bytes;
use std::collections::BTreeMap;
use zeroize::Zeroize;
pub enum CombinedKey {
Secp256k1(k256::ecdsa::SigningKey),
Ed25519(ed25519::SigningKey),
}
impl From<k256::ecdsa::SigningKey> for CombinedKey {
fn from(secret_key: k256::ecdsa::SigningKey) -> Self {
Self::Secp256k1(secret_key)
}
}
impl From<ed25519::SigningKey> for CombinedKey {
fn from(keypair: ed25519_dalek::SigningKey) -> Self {
Self::Ed25519(keypair)
}
}
impl EnrKey for CombinedKey {
type PublicKey = CombinedPublicKey;
fn sign_v4(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
match self {
Self::Secp256k1(ref key) => key.sign_v4(msg),
Self::Ed25519(ref key) => key.sign_v4(msg),
}
}
fn public(&self) -> Self::PublicKey {
match self {
Self::Secp256k1(key) => CombinedPublicKey::from(key.public()),
Self::Ed25519(key) => CombinedPublicKey::from(key.public()),
}
}
fn enr_to_public(content: &BTreeMap<Key, Bytes>) -> Result<Self::PublicKey, DecoderError> {
k256::ecdsa::SigningKey::enr_to_public(content)
.map(CombinedPublicKey::Secp256k1)
.or_else(|_| ed25519::SigningKey::enr_to_public(content).map(CombinedPublicKey::from))
}
}
impl CombinedKey {
#[must_use]
pub fn generate_secp256k1() -> Self {
let key = k256::ecdsa::SigningKey::random(&mut rand::thread_rng());
Self::Secp256k1(key)
}
#[must_use]
pub fn generate_ed25519() -> Self {
Self::Ed25519(ed25519::SigningKey::generate(&mut rand::thread_rng()))
}
pub fn secp256k1_from_bytes(bytes: &mut [u8]) -> Result<Self, DecoderError> {
let key = k256::ecdsa::SigningKey::from_slice(bytes)
.map_err(|_| DecoderError::Custom("Invalid secp256k1 secret key"))
.map(Self::from)?;
bytes.zeroize();
Ok(key)
}
pub fn ed25519_from_bytes(bytes: &mut [u8]) -> Result<Self, DecoderError> {
#[allow(clippy::useless_asref)]
let key = ed25519::SigningKey::try_from(bytes.as_ref())
.map_err(|_| DecoderError::Custom("Invalid ed25519 secret key"))
.map(Self::from)?;
bytes.zeroize();
Ok(key)
}
#[must_use]
pub fn encode(&self) -> Vec<u8> {
match self {
Self::Secp256k1(key) => key.to_bytes().to_vec(),
Self::Ed25519(key) => key.to_bytes().to_vec(),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CombinedPublicKey {
Secp256k1(k256::ecdsa::VerifyingKey),
Ed25519(ed25519::VerifyingKey),
}
impl From<k256::ecdsa::VerifyingKey> for CombinedPublicKey {
fn from(public_key: k256::ecdsa::VerifyingKey) -> Self {
Self::Secp256k1(public_key)
}
}
impl From<ed25519::VerifyingKey> for CombinedPublicKey {
fn from(public_key: ed25519::VerifyingKey) -> Self {
Self::Ed25519(public_key)
}
}
impl EnrPublicKey for CombinedPublicKey {
type Raw = Vec<u8>;
type RawUncompressed = Vec<u8>;
fn verify_v4(&self, msg: &[u8], sig: &[u8]) -> bool {
match self {
Self::Secp256k1(pk) => pk.verify_v4(msg, sig),
Self::Ed25519(pk) => pk.verify_v4(msg, sig),
}
}
fn encode(&self) -> Vec<u8> {
match self {
Self::Secp256k1(pk) => pk.encode().to_vec(),
Self::Ed25519(pk) => pk.encode().to_vec(),
}
}
fn encode_uncompressed(&self) -> Vec<u8> {
match self {
Self::Secp256k1(pk) => pk.encode_uncompressed().to_vec(),
Self::Ed25519(pk) => pk.encode_uncompressed().to_vec(),
}
}
fn enr_key(&self) -> Key {
match self {
Self::Secp256k1(key) => key.enr_key(),
Self::Ed25519(key) => key.enr_key(),
}
}
}