1 //! Signature algorithms supported by picky 2 3 use crate::hash::HashAlgorithm; 4 use crate::key::{KeyError, PrivateKey, PublicKey}; 5 use core::convert::TryFrom; 6 use picky_asn1_x509::{oids, AlgorithmIdentifier}; 7 use rsa::{PublicKey as RsaPublicKeyInterface, RSAPrivateKey, RSAPublicKey}; 8 use serde::{Deserialize, Serialize}; 9 use thiserror::Error; 10 11 #[derive(Debug, Error)] 12 #[non_exhaustive] 13 pub enum SignatureError { 14 /// Key error 15 #[error("Key error: {source}")] 16 Key { source: KeyError }, 17 18 /// RSA error 19 #[error("RSA error: {context}")] 20 Rsa { context: String }, 21 22 /// invalid signature 23 #[error("invalid signature")] 24 BadSignature, 25 26 /// unsupported algorithm 27 #[error("unsupported algorithm: {algorithm}")] 28 UnsupportedAlgorithm { algorithm: String }, 29 } 30 31 impl From<rsa::errors::Error> for SignatureError { from(e: rsa::errors::Error) -> Self32 fn from(e: rsa::errors::Error) -> Self { 33 SignatureError::Rsa { context: e.to_string() } 34 } 35 } 36 37 impl From<KeyError> for SignatureError { from(e: KeyError) -> Self38 fn from(e: KeyError) -> Self { 39 SignatureError::Key { source: e } 40 } 41 } 42 43 /// Supported signature algorithms 44 #[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)] 45 #[non_exhaustive] 46 pub enum SignatureAlgorithm { 47 RsaPkcs1v15(HashAlgorithm), 48 } 49 50 impl TryFrom<&'_ AlgorithmIdentifier> for SignatureAlgorithm { 51 type Error = SignatureError; 52 try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error>53 fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> { 54 let oid_string: String = v.oid().into(); 55 match oid_string.as_str() { 56 oids::SHA1_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA1)), 57 oids::SHA224_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_224)), 58 oids::SHA256_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_256)), 59 oids::SHA384_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_384)), 60 oids::SHA512_WITH_RSA_ENCRYPTION => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA2_512)), 61 oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_384 => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA3_384)), 62 oids::ID_RSASSA_PKCS1_V1_5_WITH_SHA3_512 => Ok(Self::RsaPkcs1v15(HashAlgorithm::SHA3_512)), 63 _ => Err(SignatureError::UnsupportedAlgorithm { algorithm: oid_string }), 64 } 65 } 66 } 67 68 impl From<SignatureAlgorithm> for AlgorithmIdentifier { from(ty: SignatureAlgorithm) -> Self69 fn from(ty: SignatureAlgorithm) -> Self { 70 match ty { 71 SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA1) => AlgorithmIdentifier::new_sha1_with_rsa_encryption(), 72 SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_224) => { 73 AlgorithmIdentifier::new_sha224_with_rsa_encryption() 74 } 75 SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_256) => { 76 AlgorithmIdentifier::new_sha256_with_rsa_encryption() 77 } 78 SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_384) => { 79 AlgorithmIdentifier::new_sha384_with_rsa_encryption() 80 } 81 SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA2_512) => { 82 AlgorithmIdentifier::new_sha512_with_rsa_encryption() 83 } 84 SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA3_384) => { 85 AlgorithmIdentifier::new_sha3_384_with_rsa_encryption() 86 } 87 SignatureAlgorithm::RsaPkcs1v15(HashAlgorithm::SHA3_512) => { 88 AlgorithmIdentifier::new_sha3_512_with_rsa_encryption() 89 } 90 } 91 } 92 } 93 94 impl SignatureAlgorithm { from_algorithm_identifier(algorithm_identifier: &AlgorithmIdentifier) -> Result<Self, SignatureError>95 pub fn from_algorithm_identifier(algorithm_identifier: &AlgorithmIdentifier) -> Result<Self, SignatureError> { 96 Self::try_from(algorithm_identifier) 97 } 98 sign(self, msg: &[u8], private_key: &PrivateKey) -> Result<Vec<u8>, SignatureError>99 pub fn sign(self, msg: &[u8], private_key: &PrivateKey) -> Result<Vec<u8>, SignatureError> { 100 let signature = match self { 101 SignatureAlgorithm::RsaPkcs1v15(picky_hash_algo) => { 102 let rsa_private_key = RSAPrivateKey::try_from(private_key)?; 103 let digest = picky_hash_algo.digest(msg); 104 let rsa_hash_algo = rsa::Hash::from(picky_hash_algo); 105 let padding_scheme = rsa::PaddingScheme::new_pkcs1v15_sign(Some(rsa_hash_algo)); 106 rsa_private_key.sign_blinded(&mut rand::rngs::OsRng, padding_scheme, &digest)? 107 } 108 }; 109 110 Ok(signature) 111 } 112 verify(self, public_key: &PublicKey, msg: &[u8], signature: &[u8]) -> Result<(), SignatureError>113 pub fn verify(self, public_key: &PublicKey, msg: &[u8], signature: &[u8]) -> Result<(), SignatureError> { 114 match self { 115 SignatureAlgorithm::RsaPkcs1v15(picky_hash_algo) => { 116 let rsa_public_key = RSAPublicKey::try_from(public_key)?; 117 let digest = picky_hash_algo.digest(msg); 118 let rsa_hash_algo = rsa::Hash::from(picky_hash_algo); 119 let padding_scheme = rsa::PaddingScheme::new_pkcs1v15_sign(Some(rsa_hash_algo)); 120 rsa_public_key 121 .verify(padding_scheme, &digest, signature) 122 .map_err(|_| SignatureError::BadSignature)?; 123 } 124 } 125 126 Ok(()) 127 } 128 } 129