use crate::errors::{
InvalidKeyBytesError, InvalidSignatureBytesError, ParseId52Error, ParseSecretKeyError,
SignatureVerificationError,
};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
type InnerPublicKey = ed25519_dalek::VerifyingKey;
type InnerSecretKey = ed25519_dalek::SigningKey;
type InnerSignature = ed25519_dalek::Signature;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct PublicKey(InnerPublicKey);
pub struct SecretKey(InnerSecretKey);
pub struct Signature(InnerSignature);
impl PublicKey {
pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, InvalidKeyBytesError> {
use ed25519_dalek::VerifyingKey;
VerifyingKey::from_bytes(bytes)
.map(PublicKey)
.map_err(|_| InvalidKeyBytesError {
expected: 32,
got: 32, })
}
pub fn to_bytes(&self) -> [u8; 32] {
*self.0.as_bytes()
}
pub fn verify(
&self,
message: &[u8],
signature: &Signature,
) -> Result<(), SignatureVerificationError> {
use ed25519_dalek::Verifier;
self.0
.verify(message, &signature.0)
.map_err(|_| SignatureVerificationError)
}
}
impl fmt::Display for PublicKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
data_encoding::BASE32_DNSSEC.encode(self.0.as_bytes())
)
}
}
impl FromStr for PublicKey {
type Err = ParseId52Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes = data_encoding::BASE32_DNSSEC
.decode(s.as_bytes())
.map_err(|e| ParseId52Error {
input: s.to_string(),
reason: format!("invalid BASE32_DNSSEC encoding: {}", e),
})?;
if bytes.len() != 32 {
return Err(ParseId52Error {
input: s.to_string(),
reason: format!("expected 32 bytes after decoding, got {}", bytes.len()),
});
}
let bytes: [u8; 32] = bytes.try_into().unwrap();
Self::from_bytes(&bytes).map_err(|_| ParseId52Error {
input: s.to_string(),
reason: "invalid public key bytes".to_string(),
})
}
}
impl Serialize for PublicKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for PublicKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
PublicKey::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl SecretKey {
pub fn generate() -> Self {
let mut rng = rand::rngs::OsRng;
SecretKey(ed25519_dalek::SigningKey::generate(&mut rng))
}
pub fn from_bytes(bytes: &[u8; 32]) -> Self {
SecretKey(ed25519_dalek::SigningKey::from_bytes(bytes))
}
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_bytes()
}
pub fn public_key(&self) -> PublicKey {
PublicKey(self.0.verifying_key())
}
pub fn id52(&self) -> String {
self.public_key().to_string()
}
pub fn sign(&self, message: &[u8]) -> Signature {
use ed25519_dalek::Signer;
Signature(self.0.sign(message))
}
}
impl fmt::Display for SecretKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", data_encoding::HEXLOWER.encode(&self.to_bytes()))
}
}
impl FromStr for SecretKey {
type Err = ParseSecretKeyError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let bytes = if s.len() == 64 {
let mut result = [0u8; 32];
data_encoding::HEXLOWER
.decode_mut(s.as_bytes(), &mut result)
.map_err(|e| ParseSecretKeyError {
reason: format!("invalid hex encoding: {:?}", e),
})?;
result
} else {
let input = s.to_ascii_uppercase();
let mut result = [0u8; 32];
data_encoding::BASE32_NOPAD
.decode_mut(input.as_bytes(), &mut result)
.map_err(|e| ParseSecretKeyError {
reason: format!("invalid base32 encoding: {:?}", e),
})?;
result
};
Ok(SecretKey::from_bytes(&bytes))
}
}
impl Serialize for SecretKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&format!("{}", self))
}
}
impl<'de> Deserialize<'de> for SecretKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
SecretKey::from_str(&s).map_err(serde::de::Error::custom)
}
}
impl Signature {
pub fn from_bytes(bytes: &[u8; 64]) -> Result<Self, InvalidSignatureBytesError> {
Ok(Signature(InnerSignature::from_bytes(bytes)))
}
pub fn to_bytes(&self) -> [u8; 64] {
self.0.to_bytes()
}
pub fn to_vec(&self) -> Vec<u8> {
self.to_bytes().to_vec()
}
}
impl From<Signature> for Vec<u8> {
fn from(sig: Signature) -> Vec<u8> {
sig.to_bytes().to_vec()
}
}
impl From<Signature> for [u8; 64] {
fn from(sig: Signature) -> [u8; 64] {
sig.to_bytes()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_public_key_roundtrip() {
let secret_key = SecretKey::generate();
let public_key = secret_key.public_key();
let id52 = public_key.to_string();
let parsed = PublicKey::from_str(&id52).unwrap();
assert_eq!(parsed, public_key);
}
#[test]
fn test_secret_key_hex_roundtrip() {
let secret_key = SecretKey::generate();
let hex = secret_key.to_string();
let parsed = SecretKey::from_str(&hex).unwrap();
assert_eq!(parsed.to_bytes(), secret_key.to_bytes());
}
#[test]
fn test_signature_verification() {
let secret_key = SecretKey::generate();
let public_key = secret_key.public_key();
let message = b"test message";
let signature = secret_key.sign(message);
assert!(public_key.verify(message, &signature).is_ok());
let wrong_message = b"wrong message";
assert!(public_key.verify(wrong_message, &signature).is_err());
}
}