use std::sync::Arc;
use auths_crypto::CryptoProvider;
use crate::clock::ClockProvider;
use crate::core::{Attestation, DevicePublicKey, VerifiedAttestation};
use crate::error::AttestationError;
use crate::types::{CanonicalDid, VerificationReport};
use crate::verify;
use crate::witness::WitnessVerifyConfig;
#[derive(Clone)]
pub struct Verifier {
provider: Arc<dyn CryptoProvider>,
clock: Arc<dyn ClockProvider>,
}
impl Verifier {
pub fn new(provider: Arc<dyn CryptoProvider>, clock: Arc<dyn ClockProvider>) -> Self {
Self { provider, clock }
}
#[cfg(feature = "native")]
pub fn native() -> Self {
Self {
provider: Arc::new(auths_crypto::RingCryptoProvider),
clock: Arc::new(crate::clock::SystemClock),
}
}
pub async fn verify_with_keys(
&self,
att: &Attestation,
issuer_pk: &DevicePublicKey,
) -> Result<VerifiedAttestation, AttestationError> {
verify::verify_with_keys_at(
att,
issuer_pk,
self.clock.now(),
true,
self.provider.as_ref(),
)
.await?;
Ok(VerifiedAttestation::from_verified(att.clone()))
}
pub async fn verify_at_time(
&self,
att: &Attestation,
issuer_pk: &DevicePublicKey,
at: chrono::DateTime<chrono::Utc>,
) -> Result<VerifiedAttestation, AttestationError> {
verify::verify_with_keys_at(att, issuer_pk, at, false, self.provider.as_ref()).await?;
Ok(VerifiedAttestation::from_verified(att.clone()))
}
pub async fn verify_chain(
&self,
attestations: &[Attestation],
root_pk: &DevicePublicKey,
) -> Result<VerificationReport, AttestationError> {
verify::verify_chain_inner(
attestations,
root_pk,
self.provider.as_ref(),
self.clock.now(),
)
.await
}
pub async fn verify_chain_with_witnesses(
&self,
attestations: &[Attestation],
root_pk: &DevicePublicKey,
witness_config: &WitnessVerifyConfig<'_>,
) -> Result<VerificationReport, AttestationError> {
let mut report = self.verify_chain(attestations, root_pk).await?;
if !report.is_valid() {
return Ok(report);
}
let quorum =
crate::witness::verify_witness_receipts(witness_config, self.provider.as_ref()).await;
if quorum.verified < quorum.required {
report.status = crate::types::VerificationStatus::InsufficientWitnesses {
required: quorum.required,
verified: quorum.verified,
};
report.warnings.push(format!(
"Witness quorum not met: {}/{} verified",
quorum.verified, quorum.required
));
}
report.witness_quorum = Some(quorum);
Ok(report)
}
pub async fn verify_device_authorization(
&self,
identity_did: &str,
device_did: &CanonicalDid,
attestations: &[Attestation],
identity_pk: &DevicePublicKey,
) -> Result<VerificationReport, AttestationError> {
verify::verify_device_authorization_inner(
identity_did,
device_did,
attestations,
identity_pk,
self.provider.as_ref(),
self.clock.now(),
)
.await
}
}