c2pa-rs

A fork of https://github.com/contentauth/c2pa-rs/
git clone git://archive.git.mtrnord.blog/mtrnords-photography-manager/c2pa-rs.git
Log | Files | Refs | README

signer.rs (8371B)


      1 // Copyright 2022 Adobe. All rights reserved.
      2 // This file is licensed to you under the Apache License,
      3 // Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
      4 // or the MIT license (http://opensource.org/licenses/MIT),
      5 // at your option.
      6 
      7 // Unless required by applicable law or agreed to in writing,
      8 // this software is distributed on an "AS IS" BASIS, WITHOUT
      9 // WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
     10 // implied. See the LICENSE-MIT and LICENSE-APACHE files for the
     11 // specific language governing permissions and limitations under
     12 // each license.
     13 use crate::{Result, SigningAlg};
     14 /// The `Signer` trait generates a cryptographic signature over a byte array.
     15 ///
     16 /// This trait exists to allow the signature mechanism to be extended.
     17 pub trait Signer {
     18     /// Returns a new byte array which is a signature over the original.
     19     fn sign(&self, data: &[u8]) -> Result<Vec<u8>>;
     20 
     21     /// Returns the algorithm of the Signer.
     22     fn alg(&self) -> SigningAlg;
     23 
     24     /// Returns the certificates as a Vec containing a Vec of DER bytes for each certificate.
     25     fn certs(&self) -> Result<Vec<Vec<u8>>>;
     26 
     27     /// Returns the size in bytes of the largest possible expected signature.
     28     /// Signing will fail if the result of the `sign` function is larger
     29     /// than this value.
     30     fn reserve_size(&self) -> usize;
     31 
     32     /// URL for time authority to time stamp the signature
     33     fn time_authority_url(&self) -> Option<String> {
     34         None
     35     }
     36 
     37     /// Additional request headers to pass to the time stamp authority.
     38     ///
     39     /// IMPORTANT: You should not include the "Content-type" header here.
     40     /// That is provided by default.
     41     fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
     42         None
     43     }
     44 
     45     fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
     46         crate::time_stamp::default_rfc3161_message(message)
     47     }
     48 
     49     /// Request RFC 3161 timestamp to be included in the manifest data
     50     /// structure.
     51     ///
     52     /// `message` is a preliminary hash of the claim
     53     ///
     54     /// The default implementation will send the request to the URL
     55     /// provided by [`Self::time_authority_url()`], if any.
     56     #[cfg(not(target_arch = "wasm32"))]
     57     fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
     58         if let Some(url) = self.time_authority_url() {
     59             if let Ok(body) = self.timestamp_request_body(message) {
     60                 let headers: Option<Vec<(String, String)>> = self.timestamp_request_headers();
     61                 return Some(crate::time_stamp::default_rfc3161_request(
     62                     &url, headers, &body, message,
     63                 ));
     64             }
     65         }
     66         None
     67     }
     68     #[cfg(target_arch = "wasm32")]
     69     fn send_timestamp_request(&self, _message: &[u8]) -> Option<Result<Vec<u8>>> {
     70         None
     71     }
     72 
     73     /// OCSP response for the signing cert if available
     74     /// This is the only C2PA supported cert revocation method.
     75     /// By pre-querying the value for a your signing cert the value can
     76     /// be cached taking pressure off of the CA (recommended by C2PA spec)
     77     fn ocsp_val(&self) -> Option<Vec<u8>> {
     78         None
     79     }
     80 
     81     /// If this returns true the sign function is responsible for for direct handling of the COSE structure.
     82     ///
     83     /// This is useful for cases where the signer needs to handle the COSE structure directly.
     84     /// Not recommended for general use.
     85     fn direct_cose_handling(&self) -> bool {
     86         false
     87     }
     88 }
     89 
     90 /// Trait to allow loading of signing credential from external sources
     91 #[allow(dead_code)] // this here for wasm builds to pass clippy  (todo: remove)
     92 pub(crate) trait ConfigurableSigner: Signer + Sized {
     93     /// Create signer form credential files
     94     #[cfg(feature = "file_io")]
     95     fn from_files<P: AsRef<std::path::Path>>(
     96         signcert_path: P,
     97         pkey_path: P,
     98         alg: SigningAlg,
     99         tsa_url: Option<String>,
    100     ) -> Result<Self> {
    101         use crate::Error;
    102 
    103         let signcert = std::fs::read(signcert_path).map_err(Error::IoError)?;
    104         let pkey = std::fs::read(pkey_path).map_err(Error::IoError)?;
    105 
    106         Self::from_signcert_and_pkey(&signcert, &pkey, alg, tsa_url)
    107     }
    108 
    109     /// Create signer from credentials data
    110     fn from_signcert_and_pkey(
    111         signcert: &[u8],
    112         pkey: &[u8],
    113         alg: SigningAlg,
    114         tsa_url: Option<String>,
    115     ) -> Result<Self>;
    116 }
    117 
    118 use async_trait::async_trait;
    119 
    120 /// The `AsyncSigner` trait generates a cryptographic signature over a byte array.
    121 ///
    122 /// This trait exists to allow the signature mechanism to be extended.
    123 ///
    124 /// Use this when the implementation is asynchronous.
    125 #[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
    126 #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
    127 pub trait AsyncSigner: Sync {
    128     /// Returns a new byte array which is a signature over the original.
    129     async fn sign(&self, data: Vec<u8>) -> Result<Vec<u8>>;
    130 
    131     /// Returns the algorithm of the Signer.
    132     fn alg(&self) -> SigningAlg;
    133 
    134     /// Returns the certificates as a Vec containing a Vec of DER bytes for each certificate.
    135     fn certs(&self) -> Result<Vec<Vec<u8>>>;
    136 
    137     /// Returns the size in bytes of the largest possible expected signature.
    138     /// Signing will fail if the result of the `sign` function is larger
    139     /// than this value.
    140     fn reserve_size(&self) -> usize;
    141 
    142     /// URL for time authority to time stamp the signature
    143     fn time_authority_url(&self) -> Option<String> {
    144         None
    145     }
    146 
    147     /// Additional request headers to pass to the time stamp authority.
    148     ///
    149     /// IMPORTANT: You should not include the "Content-type" header here.
    150     /// That is provided by default.
    151     fn timestamp_request_headers(&self) -> Option<Vec<(String, String)>> {
    152         None
    153     }
    154 
    155     fn timestamp_request_body(&self, message: &[u8]) -> Result<Vec<u8>> {
    156         crate::time_stamp::default_rfc3161_message(message)
    157     }
    158 
    159     /// Request RFC 3161 timestamp to be included in the manifest data
    160     /// structure.
    161     ///
    162     /// `message` is a preliminary hash of the claim
    163     ///
    164     /// The default implementation will send the request to the URL
    165     /// provided by [`Self::time_authority_url()`], if any.
    166     #[cfg(not(target_arch = "wasm32"))]
    167     async fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>> {
    168         // NOTE: This is currently synchronous, but may become
    169         // async in the future.
    170         if let Some(url) = self.time_authority_url() {
    171             if let Ok(body) = self.timestamp_request_body(message) {
    172                 let headers: Option<Vec<(String, String)>> = self.timestamp_request_headers();
    173                 return Some(crate::time_stamp::default_rfc3161_request(
    174                     &url, headers, &body, message,
    175                 ));
    176             }
    177         }
    178         None
    179     }
    180     #[cfg(target_arch = "wasm32")]
    181     async fn send_timestamp_request(&self, message: &[u8]) -> Option<Result<Vec<u8>>>;
    182 
    183     /// OCSP response for the signing cert if available
    184     /// This is the only C2PA supported cert revocation method.
    185     /// By pre-querying the value for a your signing cert the value can
    186     /// be cached taking pressure off of the CA (recommended by C2PA spec)
    187     async fn ocsp_val(&self) -> Option<Vec<u8>> {
    188         None
    189     }
    190 
    191     /// If this returns true the sign function is responsible for for direct handling of the COSE structure.
    192     ///
    193     /// This is useful for cases where the signer needs to handle the COSE structure directly.
    194     /// Not recommended for general use.
    195     fn direct_cose_handling(&self) -> bool {
    196         false
    197     }
    198 }
    199 
    200 #[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
    201 #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
    202 pub trait RemoteSigner: Sync {
    203     /// Returns the `CoseSign1` bytes signed by the [`RemoteSigner`].
    204     ///
    205     /// The size of returned `Vec` must match the value returned by `reserve_size`.
    206     /// This data will be embedded in the JUMBF `c2pa.signature` box of the manifest.
    207     /// `data` are the bytes of the claim to be remotely signed.
    208     async fn sign_remote(&self, data: &[u8]) -> Result<Vec<u8>>;
    209 
    210     /// Returns the size in bytes of the largest possible expected signature.
    211     ///
    212     /// Signing will fail if the result of the `sign` function is larger
    213     /// than this value.
    214     fn reserve_size(&self) -> usize;
    215 }