Skip to main content

ctclient_async/
sth.rs

1use openssl::pkey::PKey;
2
3use crate::{Error, internal};
4
5/// An unverified *signed tree head* (STH), as returned from the server. This encapsulate the state of the tree at
6/// some point in time.
7///
8/// This struct stores the signature but does not store the public key or log id.
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct SignedTreeHead {
11    pub tree_size: u64,
12    pub timestamp: u64,
13    pub root_hash: [u8; 32],
14    /// Digitally signed struct
15    pub signature: Vec<u8>,
16}
17
18impl SignedTreeHead {
19    /// Verify the contained signature against the log's public key.
20    pub fn verify(&self, pub_key: &PKey<openssl::pkey::Public>) -> Result<(), Error> {
21        let mut verify_body: Vec<u8> = Vec::new();
22        /*
23          From go source:
24          type TreeHeadSignature struct {
25            Version        Version       `tls:"maxval:255"`
26            SignatureType  SignatureType `tls:"maxval:255"` // == TreeHashSignatureType
27            Timestamp      uint64
28            TreeSize       uint64
29            SHA256RootHash SHA256Hash
30          }
31        */
32        verify_body.push(0); // Version = 0
33        verify_body.push(1); // SignatureType = TreeHashSignatureType
34        verify_body.extend_from_slice(&self.timestamp.to_be_bytes()); // Timestamp
35        verify_body.extend_from_slice(&self.tree_size.to_be_bytes()); // TreeSize
36        verify_body.extend_from_slice(&self.root_hash);
37        internal::verify_dss(&self.signature, pub_key, &verify_body).map_err(|e| match e {
38            Error::InvalidSignature(desc) => {
39                Error::InvalidSignature(format!("When checking STH signature: {}", &desc))
40            }
41            other => other,
42        })
43    }
44}