#![cfg_attr(docsrs, doc(cfg(feature = "verify-tar")))]
use std::io::{Read, Seek};
use super::{find_match, NoMatch};
use crate::verify_unsign_tar::{
tar_find_data_start_and_len, tar_read_signatures, TarFindDataStartAndLenError,
TarReadSignaturesError,
};
use crate::{Prehash, VerifyingKey};
crate::Error! {
pub struct VerifyTarError(Error) {
#[error("could not find read signatures in .tar.gz file")]
FindDataStartAndLen(#[source] TarFindDataStartAndLenError),
#[error("no matching key/signature pair found")]
NoMatch(NoMatch),
#[error("could not read input")]
Read(#[source] std::io::Error),
#[error("could not find read signatures in .tar.gz file")]
ReadSignatures(#[source] TarReadSignaturesError),
#[error("could not seek inside the input")]
Seek(#[source] std::io::Error),
}
}
pub fn verify_tar<I>(
input: &mut I,
keys: &[VerifyingKey],
context: Option<&[u8]>,
) -> Result<usize, VerifyTarError>
where
I: ?Sized + Read + Seek,
{
let (data_start, data_len) =
tar_find_data_start_and_len(input).map_err(Error::FindDataStartAndLen)?;
let signatures =
tar_read_signatures(data_start, data_len, input).map_err(Error::ReadSignatures)?;
input.rewind().map_err(Error::Seek)?;
let prehashed_message = Prehash::calculate(&mut input.take(data_start)).map_err(Error::Read)?;
let (key_idx, _) =
find_match(keys, &signatures, &prehashed_message, context).map_err(Error::NoMatch)?;
Ok(key_idx)
}