zipsign_api/verify/
tar.rs

1#![cfg_attr(docsrs, doc(cfg(feature = "verify-tar")))]
2
3use std::io::{Read, Seek};
4
5use super::{NoMatch, find_match};
6use crate::verify_unsign_tar::{
7    TarFindDataStartAndLenError, TarReadSignaturesError, tar_find_data_start_and_len,
8    tar_read_signatures,
9};
10use crate::{Prehash, VerifyingKey};
11
12crate::Error! {
13    /// An error returned by [`verify_tar()`]
14    pub struct VerifyTarError(Error) {
15        #[error("could not find read signatures in .tar.gz file")]
16        FindDataStartAndLen(#[source] TarFindDataStartAndLenError),
17        #[error("no matching key/signature pair found")]
18        NoMatch(NoMatch),
19        #[error("could not read input")]
20        Read(#[source] std::io::Error),
21        #[error("could not find read signatures in .tar.gz file")]
22        ReadSignatures(#[source] TarReadSignaturesError),
23        #[error("could not seek inside the input")]
24        Seek(#[source] std::io::Error),
25    }
26}
27
28/// Find the index of the first [`VerifyingKey`] that matches the a signature in a signed `.tar.gz`
29/// file
30pub fn verify_tar<I>(
31    input: &mut I,
32    keys: &[VerifyingKey],
33    context: Option<&[u8]>,
34) -> Result<usize, VerifyTarError>
35where
36    I: ?Sized + Read + Seek,
37{
38    // seek to start of base64 encoded signatures
39    let (data_start, data_len) =
40        tar_find_data_start_and_len(input).map_err(Error::FindDataStartAndLen)?;
41
42    // read base64 encoded signatures
43    let signatures =
44        tar_read_signatures(data_start, data_len, input).map_err(Error::ReadSignatures)?;
45
46    // pre-hash file
47    input.rewind().map_err(Error::Seek)?;
48    let prehashed_message = Prehash::calculate(&mut input.take(data_start)).map_err(Error::Read)?;
49
50    // find match
51    let (key_idx, _) =
52        find_match(keys, &signatures, &prehashed_message, context).map_err(Error::NoMatch)?;
53    Ok(key_idx)
54}