signing_alg.rs (4615B)
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 #![deny(missing_docs)] 15 16 use std::{fmt, str::FromStr}; 17 18 #[cfg(feature = "json_schema")] 19 use schemars::JsonSchema; 20 use serde::{Deserialize, Serialize}; 21 22 /// Describes the digital signature algorithms allowed by the C2PA spec. 23 /// 24 /// Per <https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_digital_signatures>: 25 /// 26 /// > All digital signatures that are stored in a C2PA Manifest shall 27 /// > be generated using one of the digital signature algorithms and 28 /// > key types listed as described in this section. 29 #[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 30 #[cfg_attr(feature = "json_schema", derive(JsonSchema))] 31 pub enum SigningAlg { 32 /// ECDSA with SHA-256 33 Es256, 34 35 /// ECDSA with SHA-384 36 Es384, 37 38 /// ECDSA with SHA-512 39 Es512, 40 41 /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256 42 Ps256, 43 44 /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384 45 Ps384, 46 47 /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512 48 Ps512, 49 50 /// Edwards-Curve DSA (Ed25519 instance only) 51 Ed25519, 52 } 53 54 impl FromStr for SigningAlg { 55 type Err = UnknownAlgorithmError; 56 57 fn from_str(alg: &str) -> Result<Self, Self::Err> { 58 match alg { 59 "es256" => Ok(Self::Es256), 60 "es384" => Ok(Self::Es384), 61 "es512" => Ok(Self::Es512), 62 "ps256" => Ok(Self::Ps256), 63 "ps384" => Ok(Self::Ps384), 64 "ps512" => Ok(Self::Ps512), 65 "ed25519" => Ok(Self::Ed25519), 66 _ => Err(UnknownAlgorithmError(alg.to_owned())), 67 } 68 } 69 } 70 71 impl fmt::Display for SigningAlg { 72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { 73 write!( 74 f, 75 "{}", 76 match self { 77 Self::Es256 => "es256", 78 Self::Es384 => "es384", 79 Self::Es512 => "es512", 80 Self::Ps256 => "ps256", 81 Self::Ps384 => "ps384", 82 Self::Ps512 => "ps512", 83 Self::Ed25519 => "ed25519", 84 } 85 ) 86 } 87 } 88 89 #[derive(Debug, PartialEq, Eq)] 90 /// This error is thrown when converting from a string to [`SigningAlg`] 91 /// if the algorithm string is unrecognized. 92 /// 93 /// The string must be one of "es256", "es384", "es512", "ps256", "ps384", 94 /// "ps512", or "ed25519". 95 pub struct UnknownAlgorithmError(String); 96 97 impl fmt::Display for UnknownAlgorithmError { 98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { 99 write!(f, "UnknownAlgorithmError({})", self.0) 100 } 101 } 102 103 impl std::error::Error for UnknownAlgorithmError {} 104 105 #[cfg(test)] 106 mod tests { 107 #![allow(clippy::expect_used)] 108 #![allow(clippy::unwrap_used)] 109 110 use super::*; 111 112 #[test] 113 fn alg_from_str() { 114 assert_eq!("es256".parse(), Ok(SigningAlg::Es256)); 115 assert_eq!("es384".parse(), Ok(SigningAlg::Es384)); 116 assert_eq!("es512".parse(), Ok(SigningAlg::Es512)); 117 assert_eq!("ps256".parse(), Ok(SigningAlg::Ps256)); 118 assert_eq!("ps384".parse(), Ok(SigningAlg::Ps384)); 119 assert_eq!("ps512".parse(), Ok(SigningAlg::Ps512)); 120 assert_eq!("ed25519".parse(), Ok(SigningAlg::Ed25519)); 121 122 let r: Result<SigningAlg, UnknownAlgorithmError> = "bogus".parse(); 123 assert_eq!(r, Err(UnknownAlgorithmError("bogus".to_string()))); 124 } 125 126 #[test] 127 fn signing_alg_impl_display() { 128 assert_eq!(format!("{}", SigningAlg::Es256), "es256"); 129 assert_eq!(format!("{}", SigningAlg::Es384), "es384"); 130 assert_eq!(format!("{}", SigningAlg::Es512), "es512"); 131 assert_eq!(format!("{}", SigningAlg::Ps256), "ps256"); 132 assert_eq!(format!("{}", SigningAlg::Ps384), "ps384"); 133 assert_eq!(format!("{}", SigningAlg::Ps512), "ps512"); 134 assert_eq!(format!("{}", SigningAlg::Ed25519), "ed25519"); 135 } 136 137 #[test] 138 fn err_impl_display() { 139 assert_eq!( 140 format!("{}", UnknownAlgorithmError("bogus".to_owned())), 141 "UnknownAlgorithmError(bogus)" 142 ); 143 } 144 }