use super::SeaError;
use base64::{engine::general_purpose, Engine as _};
use p256::ecdsa::Signature;
use p256::ecdsa::{signature::Verifier, VerifyingKey};
use serde_json::Value;
pub async fn verify(signed_data: &Value, pub_key: &str) -> Result<Value, SeaError> {
let message = signed_data
.get("m")
.and_then(|v| v.as_str())
.ok_or(SeaError::VerificationFailed)?;
let signature = signed_data
.get("s")
.and_then(|v| v.as_str())
.ok_or(SeaError::VerificationFailed)?;
let parts: Vec<&str> = pub_key.split('.').collect();
if parts.len() != 2 {
return Err(SeaError::InvalidKey);
}
let x = general_purpose::STANDARD_NO_PAD
.decode(parts[0])
.map_err(|_| SeaError::InvalidKey)?;
let y = general_purpose::STANDARD_NO_PAD
.decode(parts[1])
.map_err(|_| SeaError::InvalidKey)?;
let mut pub_bytes = vec![0x04u8];
pub_bytes.extend_from_slice(&x);
pub_bytes.extend_from_slice(&y);
let verifying_key = VerifyingKey::from_sec1_bytes(&pub_bytes)
.map_err(|e| SeaError::Crypto(format!("Invalid public key: {}", e)))?;
let sig_bytes = general_purpose::STANDARD_NO_PAD
.decode(signature)
.map_err(|_| SeaError::VerificationFailed)?;
if sig_bytes.len() != 64 {
return Err(SeaError::VerificationFailed);
}
let mut sig_array = [0u8; 64];
sig_array.copy_from_slice(&sig_bytes);
let signature =
Signature::from_bytes(&sig_array.into()).map_err(|_| SeaError::VerificationFailed)?;
verifying_key
.verify(message.as_bytes(), &signature)
.map_err(|_| SeaError::VerificationFailed)?;
serde_json::from_str(message).map_err(|e| SeaError::Crypto(format!("Invalid JSON: {}", e)))
}