zipsign_api/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
2#![forbid(unsafe_code)]
3#![allow(unknown_lints)]
4#![warn(absolute_paths_not_starting_with_crate)]
5#![warn(elided_lifetimes_in_paths)]
6#![warn(explicit_outlives_requirements)]
7#![warn(meta_variable_misuse)]
8#![warn(missing_copy_implementations)]
9#![warn(missing_debug_implementations)]
10#![warn(missing_docs)]
11#![warn(non_ascii_idents)]
12#![warn(noop_method_call)]
13#![warn(rust_2021_idioms)]
14#![warn(single_use_lifetimes)]
15#![warn(trivial_casts)]
16#![warn(unreachable_pub)]
17#![warn(unused_crate_dependencies)]
18#![warn(unused_extern_crates)]
19#![warn(unused_lifetimes)]
20#![warn(unused_results)]
21#![allow(clippy::enum_variant_names)]
22#![doc = include_str!("../README.md")]
23
24mod constants;
25pub mod sign;
26#[cfg(any(feature = "sign-zip", feature = "unsign-zip"))]
27mod sign_unsign_zip;
28pub mod unsign;
29pub mod verify;
30#[cfg(any(feature = "verify-tar", feature = "unsign-tar"))]
31mod verify_unsign_tar;
32
33use std::fmt;
34use std::io::{self, Read};
35
36#[doc(no_inline)]
37pub use ed25519_dalek::{
38    KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH, Signature, SignatureError, SigningKey,
39    VerifyingKey,
40};
41
42/// The unsigned hash of an input file
43///
44/// Use [`io::Write`] to update the prehash.
45#[derive(Clone, Default)]
46pub struct Prehash(ed25519_dalek::Sha512);
47
48impl fmt::Debug for Prehash {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        f.debug_struct("Prehash").finish_non_exhaustive()
51    }
52}
53
54impl Prehash {
55    /// Instantiate a new prehash
56    pub fn new() -> Self {
57        Self(ed25519_dalek::Sha512::default())
58    }
59
60    /// Combination of [`Prehash::new()`] and [`io::Write`]
61    pub fn calculate<I>(input: &mut I) -> io::Result<Self>
62    where
63        I: ?Sized + Read,
64    {
65        let mut this = Self::new();
66        let _: u64 = io::copy(input, &mut this.0)?;
67        Ok(this)
68    }
69}
70
71impl io::Write for Prehash {
72    #[inline]
73    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
74        self.0.write(buf)
75    }
76
77    #[inline]
78    fn flush(&mut self) -> io::Result<()> {
79        self.0.flush()
80    }
81}
82
83/// A collection of all errors this library can return
84#[non_exhaustive]
85#[derive(Debug, thiserror::Error)]
86#[error(transparent)]
87pub enum ZipsignError {
88    /// An error returned by [`gather_signature_data()`][self::sign::gather_signature_data]
89    GatherSignatureData(#[from] self::sign::GatherSignatureDataError),
90    /// An error returned by [`read_signing_keys()`][self::sign::read_signing_keys]
91    ReadSigningKeys(#[from] self::sign::ReadSigningKeysError),
92    /// An error returned by [`copy_and_sign_tar()`][self::sign::copy_and_sign_tar]
93    #[cfg(feature = "sign-tar")]
94    #[cfg_attr(docsrs, doc(cfg(feature = "sign-tar")))]
95    SignTar(#[from] self::sign::SignTarError),
96    /// An error returned by [`copy_and_sign_zip()`][self::sign::copy_and_sign_zip]
97    #[cfg(feature = "sign-zip")]
98    #[cfg_attr(docsrs, doc(cfg(feature = "sign-zip")))]
99    SignZip(#[from] self::sign::SignZipError),
100
101    /// No matching key/signature pair found
102    NoMatch(#[from] self::verify::NoMatch),
103    /// An error returned by [`collect_keys()`][self::verify::collect_keys]
104    CollectKeys(#[from] self::verify::CollectKeysError),
105    /// An error returned by [`read_signatures()`][self::verify::read_signatures]
106    ReadSignatures(#[from] self::verify::ReadSignaturesError),
107    /// An error returned by [`verify_tar()`][self::verify::verify_tar]
108    #[cfg(feature = "verify-tar")]
109    #[cfg_attr(docsrs, doc(cfg(feature = "verify-tar")))]
110    VerifyTar(#[from] self::verify::VerifyTarError),
111    /// An error returned by [`verify_zip()`][self::verify::verify_zip]
112    #[cfg(feature = "verify-zip")]
113    #[cfg_attr(docsrs, doc(cfg(feature = "verify-zip")))]
114    VerifyZip(#[from] self::verify::VerifyZipError),
115
116    /// An error returned by [`copy_and_unsign_tar()`][self::unsign::copy_and_unsign_tar]
117    #[cfg(feature = "unsign-tar")]
118    #[cfg_attr(docsrs, doc(cfg(feature = "unsign-tar")))]
119    UnsignTar(#[from] self::unsign::UnsignTarError),
120    /// An error returned by [`copy_and_unsign_zip()`][self::unsign::copy_and_unsign_zip]
121    #[cfg(feature = "unsign-zip")]
122    #[cfg_attr(docsrs, doc(cfg(feature = "unsign-zip")))]
123    UnsignZip(#[from] self::unsign::UnsignZipError),
124
125    /// An I/O occurred
126    Io(#[from] io::Error),
127}
128
129macro_rules! Error {
130    (
131        $(#[$meta:meta])+
132        $vis:vis struct $outer:ident($inner:ident) { $(
133            $(#[$field_meta:meta])+
134            $field:ident $(( $(
135                $(#[$ty_meta:meta])*
136                $field_type:ty
137            ),+ $(,)? ))?
138        ),+ $(,)? }
139    ) => {
140        $(#[$meta])+
141        $vis struct $outer(Box<$inner>);
142
143        #[derive(Debug, thiserror::Error)]
144        enum $inner { $(
145            $(#[$field_meta])+
146            $field $(( $(
147                $(#[$ty_meta])* $field_type,
148            )+ ))?,
149        )+ }
150
151        const _: () = {
152            impl std::fmt::Debug for $outer {
153                #[inline]
154                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155                    std::fmt::Debug::fmt(&*self.0, f)
156                }
157            }
158
159            impl std::fmt::Display for $outer {
160                #[inline]
161                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162                    std::fmt::Display::fmt(&*self.0, f)
163                }
164            }
165
166            impl From<$inner> for $outer {
167                #[inline]
168                fn from(value: $inner) -> Self {
169                    Self(Box::new(value))
170                }
171            }
172
173            impl std::error::Error for $outer {
174                #[inline]
175                fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
176                    self.0.source()
177                }
178            }
179        };
180    };
181}
182
183pub(crate) use Error;