#[cfg(feature = "sign-tar")]
mod tar;
#[cfg(feature = "sign-zip")]
mod zip;
use std::io::Read;
#[cfg(feature = "sign-tar")]
pub use self::tar::{copy_and_sign_tar, SignTarError};
#[cfg(feature = "sign-zip")]
pub use self::zip::{copy_and_sign_zip, SignZipError};
use crate::constants::{SignatureCountLeInt, BUF_LIMIT, HEADER_SIZE, MAGIC_HEADER};
use crate::{Prehash, SignatureError, SigningKey, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
crate::Error! {
pub struct ReadSigningKeysError(KeysError) {
#[error("input #{1} did not contain a valid key")]
Construct(#[source] ed25519_dalek::ed25519::Error, usize),
#[error("no signing keys provided")]
Empty,
#[error("could not read key in file #{1}")]
Read(#[source] std::io::Error, usize),
}
}
pub fn read_signing_keys<I, R>(inputs: I) -> Result<Vec<SigningKey>, ReadSigningKeysError>
where
I: IntoIterator<Item = std::io::Result<R>>,
R: Read,
{
let mut keys = inputs
.into_iter()
.enumerate()
.map(|(key_index, input)| {
let mut key = [0; KEYPAIR_LENGTH];
input
.and_then(|mut input| input.read_exact(&mut key))
.map_err(|err| KeysError::Read(err, key_index))?;
SigningKey::from_keypair_bytes(&key).map_err(|err| KeysError::Construct(err, key_index))
})
.collect::<Result<Vec<_>, _>>()?;
if keys.is_empty() {
return Err(KeysError::Empty.into());
}
keys.sort_by(|l, r| {
l.verifying_key()
.as_bytes()
.cmp(r.verifying_key().as_bytes())
});
Ok(keys)
}
crate::Error! {
pub struct GatherSignatureDataError(SignaturesError) {
#[error("no signing keys provided")]
Empty,
#[error("could not sign data with key #{1}")]
Signature(#[source] SignatureError, usize),
#[error("too many signing keys provided")]
TooManyKeys,
}
}
pub fn gather_signature_data(
keys: &[SigningKey],
prehashed_message: &Prehash,
context: Option<&[u8]>,
) -> Result<Vec<u8>, GatherSignatureDataError> {
if keys.is_empty() {
return Err(SignaturesError::Empty.into());
}
let signature_bytes = HEADER_SIZE + keys.len() * SIGNATURE_LENGTH;
if signature_bytes > BUF_LIMIT {
return Err(SignaturesError::TooManyKeys.into());
}
let mut header = [0; HEADER_SIZE];
header[..MAGIC_HEADER.len()].copy_from_slice(MAGIC_HEADER);
header[MAGIC_HEADER.len()..]
.copy_from_slice(&(keys.len() as SignatureCountLeInt).to_le_bytes());
let mut buf = Vec::with_capacity(signature_bytes);
buf.extend(header);
for (idx, key) in keys.iter().enumerate() {
let signature = key
.sign_prehashed(prehashed_message.0.clone(), context)
.map_err(|err| SignaturesError::Signature(err, idx))?;
buf.extend(signature.to_bytes());
}
Ok(buf)
}