use crate::cryptotensors::CryptoTensorsError;
use ring::signature;
use ring::signature::{Ed25519KeyPair, UnparsedPublicKey};
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SignatureAlgorithm {
Ed25519,
}
impl FromStr for SignatureAlgorithm {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_uppercase().as_str() {
"ED25519" => Ok(SignatureAlgorithm::Ed25519),
_ => Err(()),
}
}
}
impl fmt::Display for SignatureAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
SignatureAlgorithm::Ed25519 => "ED25519",
};
write!(f, "{}", s)
}
}
pub fn sign_data(data: &[u8], key: &[u8], algo_name: &str) -> Result<Vec<u8>, CryptoTensorsError> {
if key.is_empty() {
return Err(CryptoTensorsError::MissingSigningKey);
}
let algo = algo_name
.parse::<SignatureAlgorithm>()
.map_err(|_| CryptoTensorsError::InvalidAlgorithm(algo_name.to_string()))?;
match algo {
SignatureAlgorithm::Ed25519 => {
let key_pair = Ed25519KeyPair::from_seed_unchecked(key).map_err(|e| {
CryptoTensorsError::Signing(format!("Failed to create Ed25519 key pair: {}", e))
})?;
Ok(key_pair.sign(data).as_ref().to_vec())
}
}
}
pub fn verify_signature(
data: &[u8],
signature: &[u8],
key: &[u8],
algo_name: &str,
) -> Result<bool, CryptoTensorsError> {
if key.is_empty() {
return Err(CryptoTensorsError::MissingVerificationKey);
}
let algo = algo_name
.parse::<SignatureAlgorithm>()
.map_err(|_| CryptoTensorsError::InvalidAlgorithm(algo_name.to_string()))?;
match algo {
SignatureAlgorithm::Ed25519 => {
let public_key = UnparsedPublicKey::new(&signature::ED25519, key);
match public_key.verify(data, signature) {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}
}
}