use c2pa::{create_signer, BoxedSigner, SigningAlg};
use serde::Deserialize;
use crate::{Error, Result};
#[derive(Clone, Debug, Default, Deserialize)]
pub struct SignerInfo {
pub alg: String,
pub sign_cert: Vec<u8>,
pub private_key: Vec<u8>,
pub ta_url: Option<String>,
}
impl SignerInfo {
pub fn from_json(json: &str) -> Result<Self> {
serde_json::from_str(json).map_err(|e| Error::Json(e.to_string()))
}
fn alg(&self) -> Result<SigningAlg> {
self.alg
.to_lowercase()
.parse()
.map_err(|_| Error::Other("Invalid signing algorithm".to_string()))
}
pub fn signer(&self) -> Result<BoxedSigner> {
create_signer::from_keys(
&self.sign_cert,
&self.private_key,
self.alg()?,
self.ta_url.clone(),
)
.map_err(Error::from_c2pa_error)
}
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
#[test]
fn test_signer_info_valid() {
let json = json!({
"alg": "Es256",
"sign_cert": b"test_cert".to_vec(), "private_key": b"test_key".to_vec(), "ta_url": "https://timestamp.example.com"
})
.to_string();
let signer_info = SignerInfo::from_json(&json).unwrap();
assert_eq!(signer_info.alg, "Es256");
assert_eq!(signer_info.sign_cert, b"test_cert");
assert_eq!(signer_info.private_key, b"test_key");
assert_eq!(
signer_info.ta_url.as_deref(),
Some("https://timestamp.example.com")
);
}
#[test]
fn test_signer_info_missing_fields() {
let json = json!({
"alg": "Es256",
"sign_cert": b"test_cert".to_vec() })
.to_string();
let result = SignerInfo::from_json(&json);
assert!(result.is_err());
let signer_info = result.unwrap_err();
assert!(signer_info
.to_string()
.starts_with("Json: missing field `private_key`"));
}
#[test]
fn test_signer_info_invalid_json() {
let json = r#"
{
"alg": "Es256",
"sign_cert": [100, 71, 86, 122, 100, 70, 57, 106, 90, 88, 74, 48],
"private_key": [100, 71, 86, 122, 100, 70, 57, 114, 90, 88, 107, 61],
}
"#; let result = SignerInfo::from_json(json);
assert!(result.is_err());
}
#[test]
fn test_signer_info_invalid_algorithm() {
let json = json!({
"alg": "invalid_alg",
"sign_cert": b"test_cert".to_vec(), "private_key": b"test_key".to_vec() })
.to_string();
let signer_info = SignerInfo::from_json(&json).unwrap();
let result = signer_info.alg();
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"Other: Invalid signing algorithm"
);
}
#[test]
fn test_signer_creation_fail() {
let json = json!({
"alg": "Es256",
"sign_cert": b"test_cert".to_vec(), "private_key": b"test_key".to_vec() })
.to_string();
let signer_info = SignerInfo::from_json(&json).unwrap();
let signer = signer_info.signer();
assert!(signer.is_err());
}
}