ed_signer.rs (3593B)
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 14 use openssl::{ 15 pkey::{PKey, Private}, 16 x509::X509, 17 }; 18 19 use super::check_chain_order; 20 use crate::{signer::ConfigurableSigner, Error, Result, Signer, SigningAlg}; 21 22 /// Implements `Signer` trait using OpenSSL's implementation of 23 /// Edwards Curve encryption. 24 pub struct EdSigner { 25 signcerts: Vec<X509>, 26 pkey: PKey<Private>, 27 28 certs_size: usize, 29 timestamp_size: usize, 30 31 alg: SigningAlg, 32 tsa_url: Option<String>, 33 } 34 35 impl ConfigurableSigner for EdSigner { 36 fn from_signcert_and_pkey( 37 signcert: &[u8], 38 pkey: &[u8], 39 alg: SigningAlg, 40 tsa_url: Option<String>, 41 ) -> Result<Self> { 42 let certs_size = signcert.len(); 43 let signcerts = X509::stack_from_pem(signcert).map_err(Error::OpenSslError)?; 44 let pkey = PKey::private_key_from_pem(pkey).map_err(Error::OpenSslError)?; 45 46 if alg != SigningAlg::Ed25519 { 47 return Err(Error::UnsupportedType); // only ed25519 is supported by C2PA 48 } 49 50 // make sure cert chains are in order 51 if !check_chain_order(&signcerts) { 52 return Err(Error::BadParam( 53 "certificate chain is not in correct order".to_string(), 54 )); 55 } 56 57 Ok(EdSigner { 58 signcerts, 59 pkey, 60 certs_size, 61 timestamp_size: 10000, /* todo: call out to TSA to get actual timestamp and use that size */ 62 alg, 63 tsa_url, 64 }) 65 } 66 } 67 68 impl Signer for EdSigner { 69 fn sign(&self, data: &[u8]) -> Result<Vec<u8>> { 70 let mut signer = 71 openssl::sign::Signer::new_without_digest(&self.pkey).map_err(Error::OpenSslError)?; 72 73 let signed_data = signer.sign_oneshot_to_vec(data)?; 74 75 Ok(signed_data) 76 } 77 78 fn alg(&self) -> SigningAlg { 79 self.alg 80 } 81 82 fn certs(&self) -> Result<Vec<Vec<u8>>> { 83 let mut certs: Vec<Vec<u8>> = Vec::new(); 84 85 for c in &self.signcerts { 86 let cert = c.to_der().map_err(Error::OpenSslError)?; 87 certs.push(cert); 88 } 89 90 Ok(certs) 91 } 92 93 fn time_authority_url(&self) -> Option<String> { 94 self.tsa_url.clone() 95 } 96 97 fn reserve_size(&self) -> usize { 98 1024 + self.certs_size + self.timestamp_size // the Cose_Sign1 contains complete certs and timestamps so account for size 99 } 100 } 101 102 #[cfg(test)] 103 #[cfg(feature = "file_io")] 104 mod tests { 105 #![allow(clippy::unwrap_used)] 106 use super::*; 107 use crate::{openssl::temp_signer, utils::test::fixture_path}; 108 109 #[test] 110 fn ed25519_signer() { 111 let cert_dir = fixture_path("certs"); 112 113 let (signer, _) = temp_signer::get_ed_signer(cert_dir, SigningAlg::Ed25519, None); 114 115 let data = b"some sample content to sign"; 116 println!("data len = {}", data.len()); 117 118 let signature = signer.sign(data).unwrap(); 119 println!("signature.len = {}", signature.len()); 120 assert!(signature.len() >= 64); 121 assert!(signature.len() <= signer.reserve_size()); 122 } 123 }