use csv_adapter_core::error::AdapterError;
use csv_adapter_core::error::Result;
pub fn verify_sui_signature(signature: &[u8], public_key: &[u8], message: &[u8]) -> Result<()> {
if signature.len() != 64 {
return Err(AdapterError::SignatureVerificationFailed(format!(
"Invalid signature length: {} (expected 64)",
signature.len()
)));
}
if public_key.len() != 32 {
return Err(AdapterError::SignatureVerificationFailed(format!(
"Invalid public key length: {} (expected 32)",
public_key.len()
)));
}
if message.is_empty() {
return Err(AdapterError::SignatureVerificationFailed(
"Message cannot be empty".to_string(),
));
}
let verifying_key =
ed25519_dalek::VerifyingKey::from_bytes(public_key.try_into().map_err(|_| {
AdapterError::SignatureVerificationFailed("Invalid public key".to_string())
})?)
.map_err(|e| {
AdapterError::SignatureVerificationFailed(format!("Invalid Ed25519 public key: {}", e))
})?;
let sig =
ed25519_dalek::Signature::from_bytes(signature.try_into().map_err(|_| {
AdapterError::SignatureVerificationFailed("Invalid signature".to_string())
})?);
use ed25519_dalek::Verifier;
verifying_key.verify(message, &sig).map_err(|_| {
AdapterError::SignatureVerificationFailed(
"Ed25519 signature verification failed".to_string(),
)
})
}
pub fn verify_sui_signatures(signatures: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) -> Result<()> {
if signatures.is_empty() {
return Err(AdapterError::SignatureVerificationFailed(
"No signatures to verify".to_string(),
));
}
for (i, (sig, pk, msg)) in signatures.iter().enumerate() {
verify_sui_signature(sig, pk, msg).map_err(|e| {
AdapterError::SignatureVerificationFailed(format!(
"Signature {} verification failed: {}",
i, e
))
})?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use ed25519_dalek::Signer;
use ed25519_dalek::SigningKey;
use rand::rngs::OsRng;
fn generate_test_signature() -> (Vec<u8>, Vec<u8>, Vec<u8>) {
let mut csprng = OsRng;
let signing_key = SigningKey::generate(&mut csprng);
let verifying_key = signing_key.verifying_key();
let message = b"test message for Sui signature verification";
let signature = signing_key.sign(message);
(
signature.to_bytes().to_vec(),
verifying_key.to_bytes().to_vec(),
message.to_vec(),
)
}
#[test]
fn test_valid_sui_signature() {
let (sig, pk, msg) = generate_test_signature();
assert!(verify_sui_signature(&sig, &pk, &msg).is_ok());
}
#[test]
fn test_invalid_signature_length() {
let (_, pk, msg) = generate_test_signature();
let bad_sig = vec![0u8; 32];
assert!(verify_sui_signature(&bad_sig, &pk, &msg).is_err());
}
#[test]
fn test_invalid_public_key_length() {
let (sig, _, msg) = generate_test_signature();
let bad_pk = vec![0u8; 33];
assert!(verify_sui_signature(&sig, &bad_pk, &msg).is_err());
}
#[test]
fn test_tampered_signature() {
let (mut sig, pk, msg) = generate_test_signature();
sig[0] ^= 0xFF;
assert!(verify_sui_signature(&sig, &pk, &msg).is_err());
}
#[test]
fn test_wrong_public_key() {
let (sig, _, msg) = generate_test_signature();
let (_, wrong_pk, _) = generate_test_signature();
assert!(verify_sui_signature(&sig, &wrong_pk, &msg).is_err());
}
#[test]
fn test_wrong_message() {
let (sig, pk, _) = generate_test_signature();
let wrong_msg = b"wrong message entirely";
assert!(verify_sui_signature(&sig, &pk, wrong_msg).is_err());
}
#[test]
fn test_verify_multiple_signatures() {
let sig1 = generate_test_signature();
let sig2 = generate_test_signature();
let sig3 = generate_test_signature();
let signatures = vec![sig1, sig2, sig3];
assert!(verify_sui_signatures(&signatures).is_ok());
}
#[test]
fn test_verify_empty_signatures() {
let signatures: Vec<(Vec<u8>, Vec<u8>, Vec<u8>)> = vec![];
assert!(verify_sui_signatures(&signatures).is_err());
}
}