use std::sync::Arc;
use async_trait::async_trait;
use c2pa_raw_crypto::{RawSigner, SigningAlg};
use crate::{
crypto::cose::cose_reserve_size, dynamic_assertion::AsyncDynamicAssertion,
identity::builder::AsyncIdentityAssertionBuilder, AsyncSigner, Result,
};
pub struct AsyncIdentityAssertionSigner {
#[cfg(not(target_arch = "wasm32"))]
signer: Box<dyn RawSigner + Sync + Send>,
#[cfg(target_arch = "wasm32")]
signer: Box<dyn RawSigner>,
cert_chain: Vec<Vec<u8>>,
identity_assertions: std::sync::RwLock<Vec<Arc<AsyncIdentityAssertionBuilder>>>,
}
impl AsyncIdentityAssertionSigner {
#[cfg(not(target_arch = "wasm32"))]
pub fn new(signer: Box<dyn RawSigner + Sync + Send>, cert_chain: Vec<Vec<u8>>) -> Self {
Self {
signer,
cert_chain,
identity_assertions: std::sync::RwLock::new(vec![]),
}
}
#[cfg(target_arch = "wasm32")]
pub fn new(signer: Box<dyn RawSigner>, cert_chain: Vec<Vec<u8>>) -> Self {
Self {
signer,
cert_chain,
identity_assertions: std::sync::RwLock::new(vec![]),
}
}
#[cfg(test)]
pub(crate) fn from_test_credentials(alg: SigningAlg) -> Self {
use c2pa_raw_crypto::signer_from_private_key;
use crate::{
crypto::cert_chain_pem_to_der,
identity::tests::fixtures::cert_chain_and_private_key_for_alg,
};
let (cert_chain, private_key) = cert_chain_and_private_key_for_alg(alg);
#[allow(clippy::unwrap_used)]
Self {
signer: signer_from_private_key(&private_key, alg).unwrap(),
cert_chain: cert_chain_pem_to_der(&cert_chain).unwrap(),
identity_assertions: std::sync::RwLock::new(vec![]),
}
}
pub fn add_identity_assertion(&mut self, iab: AsyncIdentityAssertionBuilder) {
#[allow(clippy::unwrap_used)]
let mut identity_assertions = self.identity_assertions.write().unwrap();
identity_assertions.push(Arc::new(iab));
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl AsyncSigner for AsyncIdentityAssertionSigner {
async fn sign(&self, data: Vec<u8>) -> Result<Vec<u8>> {
self.signer.sign(&data).map_err(|e| e.into())
}
fn alg(&self) -> SigningAlg {
self.signer.alg()
}
fn certs(&self) -> Result<Vec<Vec<u8>>> {
Ok(self.cert_chain.clone())
}
fn reserve_size(&self) -> usize {
cose_reserve_size(
self.signer.max_signature_size(),
&self.cert_chain,
false,
None,
)
}
fn dynamic_assertions(&self) -> Vec<Box<dyn AsyncDynamicAssertion>> {
#[allow(clippy::unwrap_used)]
let identity_assertions = self.identity_assertions.read().unwrap();
identity_assertions
.iter()
.map(|ia| Box::new(Arc::clone(ia)) as Box<dyn AsyncDynamicAssertion>)
.collect()
}
}