use affinidi_secrets_resolver::secrets::{KeyType, Secret};
use async_trait::async_trait;
use ed25519_dalek::{SigningKey, ed25519::signature::SignerMut};
use zeroize::Zeroizing;
use crate::DataIntegrityError;
use crate::crypto_suites::CryptoSuite;
#[async_trait]
pub trait Signer: Send + Sync {
fn key_type(&self) -> KeyType;
fn verification_method(&self) -> &str;
#[must_use = "ignoring a sign result silently drops the produced signature"]
async fn sign(&self, data: &[u8]) -> Result<Vec<u8>, DataIntegrityError>;
fn cryptosuite(&self) -> CryptoSuite {
CryptoSuite::default_for_key_type(self.key_type()).unwrap_or(CryptoSuite::EddsaJcs2022)
}
}
#[async_trait]
impl Signer for Secret {
fn key_type(&self) -> KeyType {
self.get_key_type()
}
fn verification_method(&self) -> &str {
&self.id
}
async fn sign(&self, data: &[u8]) -> Result<Vec<u8>, DataIntegrityError> {
match self.get_key_type() {
KeyType::Ed25519 => {
let private_bytes: Zeroizing<[u8; 32]> =
Zeroizing::new(self.get_private_bytes().try_into().map_err(|_| {
DataIntegrityError::InvalidPublicKey {
codec: None,
len: self.get_private_bytes().len(),
reason: "Ed25519 private key must be exactly 32 bytes".to_string(),
}
})?);
let mut signing_key = SigningKey::from_bytes(&private_bytes);
Ok(signing_key.sign(data).to_vec())
}
#[cfg(feature = "ml-dsa")]
KeyType::MlDsa44 => {
affinidi_crypto::ml_dsa::sign_ml_dsa_44(self.get_private_bytes(), data)
.map_err(DataIntegrityError::signing)
}
#[cfg(feature = "ml-dsa")]
KeyType::MlDsa65 => {
affinidi_crypto::ml_dsa::sign_ml_dsa_65(self.get_private_bytes(), data)
.map_err(DataIntegrityError::signing)
}
#[cfg(feature = "ml-dsa")]
KeyType::MlDsa87 => {
affinidi_crypto::ml_dsa::sign_ml_dsa_87(self.get_private_bytes(), data)
.map_err(DataIntegrityError::signing)
}
#[cfg(feature = "slh-dsa")]
KeyType::SlhDsaSha2_128s => {
affinidi_crypto::slh_dsa::sign_slh_dsa_sha2_128s(self.get_private_bytes(), data)
.map_err(DataIntegrityError::signing)
}
other => Err(DataIntegrityError::UnsupportedCryptoSuite {
name: format!("(no signer compiled in for key type {other:?})"),
}),
}
}
}