nonce_auth/nonce/
verifier.rs1use hmac::Mac;
2
3use crate::NonceCredential;
4use crate::nonce::{NonceError, NonceServer};
5use crate::storage::NonceStorage;
6
7#[must_use = "The verifier does nothing unless one of the `verify` methods is called."]
11pub struct CredentialVerifier<'a, S: NonceStorage> {
12 server: &'a NonceServer<S>,
13 credential: &'a NonceCredential,
14 context: Option<&'a str>,
15 secret: Option<&'a [u8]>,
16}
17
18impl<'a, S: NonceStorage> CredentialVerifier<'a, S> {
19 pub(crate) fn new(server: &'a NonceServer<S>, credential: &'a NonceCredential) -> Self {
21 Self {
22 server,
23 credential,
24 context: None,
25 secret: None,
26 }
27 }
28
29 pub fn with_context(mut self, context: Option<&'a str>) -> Self {
33 self.context = context;
34 self
35 }
36
37 pub fn with_secret(mut self, secret: &'a [u8]) -> Self {
41 self.secret = Some(secret);
42 self
43 }
44
45 pub async fn verify(self, payload: &[u8]) -> Result<(), NonceError> {
54 let timestamp_str = self.credential.timestamp.to_string();
55 let nonce_str = &self.credential.nonce;
56
57 self.verify_with(|mac| {
58 mac.update(timestamp_str.as_bytes());
59 mac.update(nonce_str.as_bytes());
60 mac.update(payload);
61 })
62 .await
63 }
64
65 pub async fn verify_with<F>(self, signature_builder: F) -> Result<(), NonceError>
79 where
80 F: FnOnce(&mut hmac::Hmac<sha2::Sha256>),
81 {
82 let secret = self.secret.ok_or_else(|| {
83 NonceError::CryptoError("Secret key must be provided using with_secret()".to_string())
84 })?;
85
86 self.server.verify_timestamp(self.credential.timestamp)?;
87 NonceServer::<S>::verify_signature(secret, &self.credential.signature, signature_builder)?;
88 self.server
89 .verify_and_consume_nonce(&self.credential.nonce, self.context)
90 .await
91 }
92}