tlsn_core/attestation/
proof.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    attestation::{Attestation, Body, Header},
7    hash::HashAlgorithm,
8    merkle::{MerkleProof, MerkleTree},
9    serialize::CanonicalSerialize,
10    signing::{Signature, VerifyingKey},
11    CryptoProvider,
12};
13
14/// Proof of an attestation.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct AttestationProof {
17    signature: Signature,
18    header: Header,
19    body: BodyProof,
20}
21
22impl AttestationProof {
23    pub(crate) fn new(
24        provider: &CryptoProvider,
25        attestation: &Attestation,
26    ) -> Result<Self, AttestationError> {
27        let hasher = provider
28            .hash
29            .get(&attestation.header.root.alg)
30            .map_err(|e| AttestationError::new(ErrorKind::Provider, e))?;
31
32        let body = BodyProof::new(hasher, attestation.body.clone())?;
33
34        Ok(Self {
35            signature: attestation.signature.clone(),
36            header: attestation.header.clone(),
37            body,
38        })
39    }
40
41    /// Returns the verifying key.
42    pub fn verifying_key(&self) -> &VerifyingKey {
43        self.body.verifying_key()
44    }
45
46    /// Verifies the attestation proof.
47    ///
48    /// # Arguments
49    ///
50    /// * `provider` - Cryptography provider.
51    /// * `verifying_key` - Verifying key for the Notary signature.
52    pub fn verify(self, provider: &CryptoProvider) -> Result<Attestation, AttestationError> {
53        let signature_verifier = provider
54            .signature
55            .get(&self.signature.alg)
56            .map_err(|e| AttestationError::new(ErrorKind::Provider, e))?;
57
58        // Verify that the body is corresponding to the header.
59        let body = self.body.verify_with_provider(provider, &self.header)?;
60
61        // Verify signature of the header.
62        signature_verifier
63            .verify(
64                &body.verifying_key.data,
65                &CanonicalSerialize::serialize(&self.header),
66                &self.signature.data,
67            )
68            .map_err(|e| AttestationError::new(ErrorKind::Signature, e))?;
69
70        Ok(Attestation {
71            signature: self.signature,
72            header: self.header,
73            body,
74        })
75    }
76}
77
78/// Proof of an attestation body.
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub(crate) struct BodyProof {
81    body: Body,
82    /// A proof of inclusion of a subset of fields in the `body`.
83    // Currently, proves the inclusion of all fields.
84    proof: MerkleProof,
85}
86
87impl BodyProof {
88    /// Returns a new body proof.
89    // TODO: Support creating a proof for a subset of fields instead of the entire
90    // body.
91    pub(crate) fn new(
92        hasher: &dyn HashAlgorithm,
93        body: Body,
94    ) -> Result<BodyProof, AttestationError> {
95        let (indices, leaves): (Vec<_>, Vec<_>) = body
96            .hash_fields(hasher)
97            .into_iter()
98            .map(|(id, hash)| (id.0 as usize, hash))
99            .unzip();
100
101        let mut tree = MerkleTree::new(hasher.id());
102        tree.insert(hasher, leaves);
103
104        let proof = tree.proof(&indices);
105
106        Ok(BodyProof { body, proof })
107    }
108
109    pub(crate) fn verifying_key(&self) -> &VerifyingKey {
110        &self.body.verifying_key.data
111    }
112
113    /// Verifies the proof against the attestation header.
114    pub(crate) fn verify_with_provider(
115        self,
116        provider: &CryptoProvider,
117        header: &Header,
118    ) -> Result<Body, AttestationError> {
119        let hasher = provider
120            .hash
121            .get(&header.root.alg)
122            .map_err(|e| AttestationError::new(ErrorKind::Provider, e))?;
123
124        let fields = self
125            .body
126            .hash_fields(hasher)
127            .into_iter()
128            .map(|(id, hash)| (id.0 as usize, hash));
129
130        self.proof
131            .verify(hasher, &header.root, fields)
132            .map_err(|e| AttestationError::new(ErrorKind::Body, e))?;
133
134        Ok(self.body)
135    }
136}
137
138/// Error for [`AttestationProof`].
139#[derive(Debug, thiserror::Error)]
140pub struct AttestationError {
141    kind: ErrorKind,
142    source: Option<Box<dyn std::error::Error + Send + Sync>>,
143}
144
145impl AttestationError {
146    fn new<E>(kind: ErrorKind, source: E) -> Self
147    where
148        E: Into<Box<dyn std::error::Error + Send + Sync>>,
149    {
150        Self {
151            kind,
152            source: Some(source.into()),
153        }
154    }
155}
156
157impl fmt::Display for AttestationError {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        f.write_str("attestation proof error: ")?;
160
161        match self.kind {
162            ErrorKind::Provider => f.write_str("provider error")?,
163            ErrorKind::Signature => f.write_str("signature error")?,
164            ErrorKind::Body => f.write_str("body proof error")?,
165        }
166
167        if let Some(source) = &self.source {
168            write!(f, " caused by: {}", source)?;
169        }
170
171        Ok(())
172    }
173}
174
175#[derive(Debug)]
176enum ErrorKind {
177    Provider,
178    Signature,
179    Body,
180}