use async_trait::async_trait;
use crate::{
crypto::raw_signature::{AsyncRawSigner, SigningAlg},
dynamic_assertion::AsyncDynamicAssertion,
identity::builder::AsyncIdentityAssertionBuilder,
AsyncSigner, Result,
};
pub struct AsyncIdentityAssertionSigner {
#[cfg(not(target_arch = "wasm32"))]
signer: Box<dyn AsyncRawSigner + Sync + Send>,
#[cfg(target_arch = "wasm32")]
signer: Box<dyn AsyncRawSigner>,
identity_assertions: std::sync::RwLock<Vec<AsyncIdentityAssertionBuilder>>,
}
impl AsyncIdentityAssertionSigner {
#[cfg(not(target_arch = "wasm32"))]
pub fn new(signer: Box<dyn AsyncRawSigner + Sync + Send>) -> Self {
Self {
signer,
identity_assertions: std::sync::RwLock::new(vec![]),
}
}
#[cfg(target_arch = "wasm32")]
pub fn new(signer: Box<dyn AsyncRawSigner>) -> Self {
Self {
signer,
identity_assertions: std::sync::RwLock::new(vec![]),
}
}
#[cfg(test)]
pub(crate) fn from_test_credentials(alg: SigningAlg) -> Self {
use crate::{
crypto::raw_signature::async_signer_from_cert_chain_and_private_key,
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: async_signer_from_cert_chain_and_private_key(
&cert_chain,
&private_key,
alg,
None,
)
.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(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).await.map_err(|e| e.into())
}
fn alg(&self) -> SigningAlg {
self.signer.alg()
}
fn certs(&self) -> Result<Vec<Vec<u8>>> {
self.signer.cert_chain().map_err(|e| e.into())
}
fn reserve_size(&self) -> usize {
self.signer.reserve_size()
}
async fn ocsp_val(&self) -> Option<Vec<u8>> {
self.signer.ocsp_response().await
}
fn time_authority_url(&self) -> Option<String> {
self.signer.time_stamp_service_url()
}
fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
self.signer.time_stamp_request_headers()
}
fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
self.signer
.time_stamp_request_body(message)
.map_err(|e| e.into())
}
async fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
self.signer
.send_time_stamp_request(message)
.await
.map(|r| r.map_err(|e| e.into()))
}
fn async_raw_signer(&self) -> Option<Box<&dyn AsyncRawSigner>> {
Some(Box::new(&*self.signer))
}
fn dynamic_assertions(&self) -> Vec<Box<dyn AsyncDynamicAssertion>> {
#[allow(clippy::unwrap_used)]
let mut identity_assertions = self.identity_assertions.write().unwrap();
let ia_clone = identity_assertions.split_off(0);
let mut dynamic_assertions: Vec<Box<dyn AsyncDynamicAssertion>> = vec![];
for ia in ia_clone.into_iter() {
dynamic_assertions.push(Box::new(ia));
}
dynamic_assertions
}
}