pub use ed25519_dalek::{Keypair as Ed25519, EXPANDED_SECRET_KEY_LENGTH as ED25519_KEYPAIR_SIZE};
use serde::{de, ser, Deserialize, Serialize};
use subtle_encoding::{Base64, Encoding};
use zeroize::Zeroizing;
use crate::{prelude::*, public_key::PublicKey};
#[derive(Serialize, Deserialize)]
#[non_exhaustive]
#[serde(tag = "type", content = "value")] pub enum PrivateKey {
#[serde(
rename = "tendermint/PrivKeyEd25519",
serialize_with = "serialize_ed25519_keypair",
deserialize_with = "deserialize_ed25519_keypair"
)]
Ed25519(Ed25519),
}
impl PrivateKey {
pub fn public_key(&self) -> PublicKey {
match self {
PrivateKey::Ed25519(private_key) => private_key.public.into(),
}
}
pub fn ed25519_keypair(&self) -> Option<&Ed25519> {
match self {
PrivateKey::Ed25519(keypair) => Some(keypair),
}
}
}
fn serialize_ed25519_keypair<S>(keypair: &Ed25519, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
let keypair_bytes = Zeroizing::new(keypair.to_bytes());
Zeroizing::new(String::from_utf8(Base64::default().encode(&keypair_bytes[..])).unwrap())
.serialize(serializer)
}
fn deserialize_ed25519_keypair<'de, D>(deserializer: D) -> Result<Ed25519, D::Error>
where
D: de::Deserializer<'de>,
{
use de::Error;
let string = Zeroizing::new(String::deserialize(deserializer)?);
let mut keypair_bytes = Zeroizing::new([0u8; ED25519_KEYPAIR_SIZE]);
let decoded_len = Base64::default()
.decode_to_slice(string.as_bytes(), &mut *keypair_bytes)
.map_err(D::Error::custom)?;
if decoded_len != ED25519_KEYPAIR_SIZE {
return Err(D::Error::custom("invalid Ed25519 keypair size"));
}
Ed25519::from_bytes(&*keypair_bytes).map_err(D::Error::custom)
}