use ed25519_dalek::Signer;
use sha2::{Digest, Sha256};
use signature::SignatureEncoding;
pub enum EdwardsVerifyingKey {
Ed25519(ed25519_dalek::VerifyingKey),
Ed448(ed448_goldilocks::VerifyingKey),
}
#[expect(clippy::large_enum_variant)]
pub enum EdwardsSigningKey {
Ed25519(ed25519_dalek::SigningKey),
Ed448(ed448_goldilocks::SigningKey),
}
impl EdwardsVerifyingKey {
pub fn raw_key(&self) -> Vec<u8> {
match &self {
Self::Ed25519(key) => key.as_bytes().to_vec(),
Self::Ed448(key) => key.as_bytes().to_vec(),
}
}
pub fn verifies(&self, signature: &[u8], message: &[u8]) -> bool {
match &self {
Self::Ed25519(key) => {
let Ok(signature) = ed25519_dalek::Signature::from_slice(signature) else {
return false;
};
key.verify_strict(message, &signature).is_ok()
}
Self::Ed448(key) => {
let Ok(signature) = ed448_goldilocks::Signature::from_slice(signature) else {
return false;
};
key.verify_raw(&signature, message).is_ok()
}
}
}
pub fn from_raw_key(raw_key: &[u8]) -> Option<Self> {
match raw_key.len() {
ed25519_dalek::PUBLIC_KEY_LENGTH => {
#[allow(clippy::missing_panics_doc)]
let raw_key: &[u8; ed25519_dalek::PUBLIC_KEY_LENGTH] = raw_key
.try_into()
.expect("<&[u8;T]>::try_from(&[u8]) should succeed if <&[u8]>::len() == T");
let key = ed25519_dalek::VerifyingKey::from_bytes(raw_key).ok()?;
Some(Self::Ed25519(key))
}
ed448_goldilocks::PUBLIC_KEY_LENGTH => {
#[allow(clippy::missing_panics_doc)]
let raw_key: &[u8; ed448_goldilocks::PUBLIC_KEY_LENGTH] = raw_key
.try_into()
.expect("<&[u8;T]>::try_from(&[u8]) should succeed if <&[u8]>::len() == T");
let key = ed448_goldilocks::VerifyingKey::from_bytes(raw_key).ok()?;
Some(Self::Ed448(key))
}
_ => None,
}
}
pub fn key_id(&self) -> Vec<u8> {
let key = self.raw_key();
let digest = Sha256::digest(key);
digest.to_vec()
}
}
impl EdwardsSigningKey {
pub fn sign(&self, message: &[u8]) -> Vec<u8> {
match &self {
Self::Ed25519(key) => key.sign(message).to_vec(),
Self::Ed448(key) => key.sign_raw(message).to_bytes().to_vec(),
}
}
pub fn verifying_key(&self) -> EdwardsVerifyingKey {
match &self {
Self::Ed25519(key) => EdwardsVerifyingKey::Ed25519(key.verifying_key()),
Self::Ed448(key) => EdwardsVerifyingKey::Ed448(key.verifying_key()),
}
}
}