use async_trait::async_trait;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(Debug, Clone, thiserror::Error)]
#[non_exhaustive]
pub enum CryptoError {
#[error("Invalid signature")]
InvalidSignature,
#[error("Invalid public key length: expected {expected}, got {actual}")]
InvalidKeyLength { expected: usize, actual: usize },
#[error("Invalid private key: {0}")]
InvalidPrivateKey(String),
#[error("Crypto operation failed: {0}")]
OperationFailed(String),
#[error("Operation not supported on current compilation target")]
UnsupportedTarget,
}
impl crate::AuthsErrorInfo for CryptoError {
fn error_code(&self) -> &'static str {
match self {
Self::InvalidSignature => "AUTHS-E1001",
Self::InvalidKeyLength { .. } => {
"
"
}
Self::InvalidPrivateKey(_) => "AUTHS-E1003",
Self::OperationFailed(_) => "AUTHS-E1004",
Self::UnsupportedTarget => "AUTHS-E1005",
}
}
fn suggestion(&self) -> Option<&'static str> {
match self {
Self::InvalidSignature => Some("The signature does not match the data or public key"),
Self::InvalidKeyLength { .. } => Some("Ensure the key is exactly 32 bytes for Ed25519"),
Self::UnsupportedTarget => {
Some("This operation is not available on the current platform")
}
_ => None,
}
}
}
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct SecureSeed([u8; 32]);
impl SecureSeed {
pub fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}
impl std::fmt::Debug for SecureSeed {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("SecureSeed([REDACTED])")
}
}
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
pub trait CryptoProvider: Send + Sync {
async fn verify_ed25519(
&self,
pubkey: &[u8],
message: &[u8],
signature: &[u8],
) -> Result<(), CryptoError>;
async fn sign_ed25519(&self, seed: &SecureSeed, message: &[u8])
-> Result<Vec<u8>, CryptoError>;
async fn generate_ed25519_keypair(&self) -> Result<(SecureSeed, [u8; 32]), CryptoError>;
async fn ed25519_public_key_from_seed(
&self,
seed: &SecureSeed,
) -> Result<[u8; 32], CryptoError>;
}
pub const ED25519_PUBLIC_KEY_LEN: usize = 32;
pub const ED25519_SIGNATURE_LEN: usize = 64;