auths_verifier/
verifier.rs1use std::sync::Arc;
4
5use auths_crypto::CryptoProvider;
6
7use crate::clock::ClockProvider;
8use crate::core::{Attestation, Capability, VerifiedAttestation};
9use crate::error::AttestationError;
10use crate::types::{DeviceDID, VerificationReport};
11use crate::verify;
12use crate::witness::WitnessVerifyConfig;
13
14#[derive(Clone)]
29pub struct Verifier {
30 provider: Arc<dyn CryptoProvider>,
31 clock: Arc<dyn ClockProvider>,
32}
33
34impl Verifier {
35 pub fn new(provider: Arc<dyn CryptoProvider>, clock: Arc<dyn ClockProvider>) -> Self {
41 Self { provider, clock }
42 }
43
44 #[cfg(feature = "native")]
46 pub fn native() -> Self {
47 Self {
48 provider: Arc::new(auths_crypto::RingCryptoProvider),
49 clock: Arc::new(crate::clock::SystemClock),
50 }
51 }
52
53 pub async fn verify_with_keys(
59 &self,
60 att: &Attestation,
61 issuer_pk_bytes: &[u8],
62 ) -> Result<VerifiedAttestation, AttestationError> {
63 verify::verify_with_keys_at(
64 att,
65 issuer_pk_bytes,
66 self.clock.now(),
67 true,
68 self.provider.as_ref(),
69 )
70 .await?;
71 Ok(VerifiedAttestation::from_verified(att.clone()))
72 }
73
74 pub async fn verify_with_capability(
81 &self,
82 att: &Attestation,
83 required: &Capability,
84 issuer_pk_bytes: &[u8],
85 ) -> Result<VerifiedAttestation, AttestationError> {
86 let verified = self.verify_with_keys(att, issuer_pk_bytes).await?;
87 if !att.capabilities.contains(required) {
88 return Err(AttestationError::MissingCapability {
89 required: required.clone(),
90 available: att.capabilities.clone(),
91 });
92 }
93 Ok(verified)
94 }
95
96 pub async fn verify_at_time(
103 &self,
104 att: &Attestation,
105 issuer_pk_bytes: &[u8],
106 at: chrono::DateTime<chrono::Utc>,
107 ) -> Result<VerifiedAttestation, AttestationError> {
108 verify::verify_with_keys_at(att, issuer_pk_bytes, at, false, self.provider.as_ref())
109 .await?;
110 Ok(VerifiedAttestation::from_verified(att.clone()))
111 }
112
113 pub async fn verify_chain(
119 &self,
120 attestations: &[Attestation],
121 root_pk: &[u8],
122 ) -> Result<VerificationReport, AttestationError> {
123 verify::verify_chain_inner(
124 attestations,
125 root_pk,
126 self.provider.as_ref(),
127 self.clock.now(),
128 )
129 .await
130 }
131
132 pub async fn verify_chain_with_capability(
139 &self,
140 attestations: &[Attestation],
141 required: &Capability,
142 root_pk: &[u8],
143 ) -> Result<VerificationReport, AttestationError> {
144 let report = self.verify_chain(attestations, root_pk).await?;
145 if !report.is_valid() {
146 return Ok(report);
147 }
148 if attestations.is_empty() {
149 return Ok(report);
150 }
151
152 use std::collections::HashSet;
153 let mut effective: HashSet<Capability> =
154 attestations[0].capabilities.iter().cloned().collect();
155 for att in attestations.iter().skip(1) {
156 let att_caps: HashSet<Capability> = att.capabilities.iter().cloned().collect();
157 effective = effective.intersection(&att_caps).cloned().collect();
158 }
159 if !effective.contains(required) {
160 return Err(AttestationError::MissingCapability {
161 required: required.clone(),
162 available: effective.into_iter().collect(),
163 });
164 }
165 Ok(report)
166 }
167
168 pub async fn verify_chain_with_witnesses(
175 &self,
176 attestations: &[Attestation],
177 root_pk: &[u8],
178 witness_config: &WitnessVerifyConfig<'_>,
179 ) -> Result<VerificationReport, AttestationError> {
180 let mut report = self.verify_chain(attestations, root_pk).await?;
181 if !report.is_valid() {
182 return Ok(report);
183 }
184
185 let quorum =
186 crate::witness::verify_witness_receipts(witness_config, self.provider.as_ref()).await;
187 if quorum.verified < quorum.required {
188 report.status = crate::types::VerificationStatus::InsufficientWitnesses {
189 required: quorum.required,
190 verified: quorum.verified,
191 };
192 report.warnings.push(format!(
193 "Witness quorum not met: {}/{} verified",
194 quorum.verified, quorum.required
195 ));
196 }
197 report.witness_quorum = Some(quorum);
198 Ok(report)
199 }
200
201 pub async fn verify_device_authorization(
209 &self,
210 identity_did: &str,
211 device_did: &DeviceDID,
212 attestations: &[Attestation],
213 identity_pk: &[u8],
214 ) -> Result<VerificationReport, AttestationError> {
215 verify::verify_device_authorization_inner(
216 identity_did,
217 device_did,
218 attestations,
219 identity_pk,
220 self.provider.as_ref(),
221 self.clock.now(),
222 )
223 .await
224 }
225}