use borsh::{BorshDeserialize, BorshSerialize};
use ed25519_dalek::{ExpandedSecretKey, PublicKey, SecretKey, Signature, Verifier};
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::{
fmt::Display,
hash::{Hash, Hasher},
io::{Error as IoError, ErrorKind},
str::FromStr,
};
use super::{split_encoded_str, Error, Key, Result, ED25519};
pub use ed25519_dalek::{
KEYPAIR_LENGTH as ED25519_KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH as ED25519_PUBLIC_KEY_LENGTH,
SECRET_KEY_LENGTH as ED25519_SECRET_KEY_LENGTH, SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH,
};
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
pub struct Ed25519PublicKey(PublicKey);
impl Ed25519PublicKey {
pub fn verify(&self, data: &[u8], signature: &Ed25519Signature) -> Result<()> {
self.0
.verify(data, &signature.0)
.map_err(|_| Error::Verification(signature.string()))
}
#[inline]
pub fn as_bytes(&self) -> &[u8; ED25519_PUBLIC_KEY_LENGTH] {
self.0.as_bytes()
}
}
impl Key<ED25519_PUBLIC_KEY_LENGTH> for Ed25519PublicKey {
const KEY_TYPE: &'static str = ED25519;
#[inline]
fn to_bytes(&self) -> [u8; ED25519_PUBLIC_KEY_LENGTH] {
self.0.to_bytes()
}
fn try_from_bytes(buf: &[u8]) -> Result<Self> {
PublicKey::from_bytes(buf)
.map(Self)
.map_err(|err| Error::from_bytes::<Ed25519PublicKey>(buf, err.to_string()))
}
}
impl BorshDeserialize for Ed25519PublicKey {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
let temp_buf = std::mem::take(buf)
.split_first()
.map(|(.., key)| key)
.unwrap_or_default();
Ed25519PublicKey::try_from_bytes(temp_buf)
.map_err(|err| IoError::new(ErrorKind::InvalidData, err))
}
}
impl BorshSerialize for Ed25519PublicKey {
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
BorshSerialize::serialize(&0_u8, writer)?;
writer.write_all(self.0.as_bytes())
}
}
impl From<&Ed25519SecretKey> for Ed25519PublicKey {
fn from(sk: &Ed25519SecretKey) -> Self {
Self(PublicKey::from(&sk.0))
}
}
#[allow(clippy::derived_hash_with_manual_eq)]
impl Hash for Ed25519PublicKey {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u8(0u8);
state.write(self.0.as_bytes());
}
}
impl Display for Ed25519PublicKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.string())
}
}
pub struct Ed25519SecretKey(SecretKey);
impl Ed25519SecretKey {
pub fn sign(&self, data: &[u8], public_key: &Ed25519PublicKey) -> Ed25519Signature {
let expanded_key = ExpandedSecretKey::from(&self.0);
Ed25519Signature(expanded_key.sign(data, &public_key.0))
}
pub fn from_expanded(key: &str) -> Result<Self> {
let (key_type, bs58_encoded) = split_encoded_str(key)?;
if key_type != Self::KEY_TYPE {
return Err(Error::WrongKeyType {
key_type: key_type.to_owned(),
expected_key_type: Self::KEY_TYPE,
});
}
let expanded_key_bytes = bs58::decode(bs58_encoded)
.into_vec()
.map_err(|err| {
Error::from_string::<Ed25519SecretKey>(bs58_encoded.to_owned(), err.to_string())
})?
.into_iter()
.take(ED25519_SECRET_KEY_LENGTH)
.collect_vec();
Self::try_from_bytes(&expanded_key_bytes)
}
#[inline]
pub fn as_bytes(&self) -> &[u8; ED25519_PUBLIC_KEY_LENGTH] {
self.0.as_bytes()
}
}
impl Key<ED25519_SECRET_KEY_LENGTH> for Ed25519SecretKey {
const KEY_TYPE: &'static str = ED25519;
#[inline]
fn to_bytes(&self) -> [u8; ED25519_SECRET_KEY_LENGTH] {
self.0.to_bytes()
}
fn try_from_bytes(buf: &[u8]) -> Result<Self> {
SecretKey::from_bytes(buf)
.map(Self)
.map_err(|err| Error::from_bytes::<Ed25519SecretKey>(buf, err.to_string()))
}
}
impl BorshDeserialize for Ed25519SecretKey {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
Ed25519SecretKey::try_from_bytes(std::mem::take(buf))
.map_err(|err| IoError::new(ErrorKind::InvalidData, err))
}
}
impl BorshSerialize for Ed25519SecretKey {
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_all(self.0.as_bytes())
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Ed25519Signature(Signature);
impl Key<ED25519_SIGNATURE_LENGTH> for Ed25519Signature {
const KEY_TYPE: &'static str = ED25519;
#[inline]
fn to_bytes(&self) -> [u8; ED25519_SIGNATURE_LENGTH] {
self.0.to_bytes()
}
fn try_from_bytes(buf: &[u8]) -> Result<Self> {
Signature::from_bytes(buf)
.map(Self)
.map_err(|err| Error::from_bytes::<Ed25519Signature>(buf, err.to_string()))
}
}
impl BorshDeserialize for Ed25519Signature {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
let temp_buf = std::mem::take(buf)
.split_first()
.map(|(.., key)| key)
.unwrap_or_default();
Ed25519Signature::try_from_bytes(temp_buf)
.map_err(|err| IoError::new(ErrorKind::InvalidData, err))
}
}
impl BorshSerialize for Ed25519Signature {
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
BorshSerialize::serialize(&0_u8, writer)?;
writer.write_all(&self.0.to_bytes())
}
}
#[allow(clippy::derived_hash_with_manual_eq)]
impl Hash for Ed25519Signature {
fn hash<H: Hasher>(&self, state: &mut H) {
self.to_bytes().hash(state);
}
}
impl Display for Ed25519Signature {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.string())
}
}
#[derive(Serialize, Deserialize)]
pub struct Keypair {
public_key: Ed25519PublicKey,
secret_key: Ed25519SecretKey,
}
impl Keypair {
pub fn new(secret_key: Ed25519SecretKey) -> Self {
let public_key = Ed25519PublicKey::from(&secret_key);
Self {
public_key,
secret_key,
}
}
pub fn from_expanded_secret(expanded: &str) -> Result<Self> {
let secret_key = Ed25519SecretKey::from_expanded(expanded)?;
let public_key = Ed25519PublicKey::from(&secret_key);
Ok(Self {
public_key,
secret_key,
})
}
pub fn sign(&self, data: &[u8]) -> Ed25519Signature {
self.secret_key.sign(data, &self.public_key)
}
pub fn verify(&self, data: &[u8], signature: &Ed25519Signature) -> Result<()> {
self.public_key.verify(data, signature)
}
pub fn public_key(&self) -> &Ed25519PublicKey {
&self.public_key
}
pub fn secret_key(&self) -> &Ed25519SecretKey {
&self.secret_key
}
}
impl ToString for Keypair {
fn to_string(&self) -> String {
let keypair_bytes = self
.secret_key()
.as_bytes()
.iter()
.chain(self.public_key().as_bytes().iter())
.copied()
.collect_vec();
format!("{ED25519}:{}", bs58::encode(keypair_bytes).into_string())
}
}
impl FromStr for Keypair {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
let (key_type, data) = split_encoded_str(s)?;
if key_type != ED25519 {
return Err(Error::WrongKeyType {
key_type: key_type.to_owned(),
expected_key_type: ED25519,
});
}
let byte_data = bs58::decode(data)
.into_vec()
.map_err(|err| Error::from_string::<Keypair>(data.to_owned(), err.to_string()))?;
if byte_data.len() != ED25519_KEYPAIR_LENGTH {
return Err(Error::from_bytes::<Keypair>(
&byte_data,
format!(
"Keypair byte array length doesn't equal\
to requested length {ED25519_KEYPAIR_LENGTH}"
),
));
}
Ok(Self {
secret_key: Ed25519SecretKey::try_from_bytes(&byte_data[..ED25519_SECRET_KEY_LENGTH])?,
public_key: Ed25519PublicKey::try_from_bytes(&byte_data[ED25519_SECRET_KEY_LENGTH..])?,
})
}
}
serde_impl!(Ed25519PublicKey);
serde_impl!(Ed25519SecretKey);
serde_impl!(Ed25519Signature);