did_crypto/crypto/
rsa.rs

1use crate::{
2    algorithms::Algorithm, crypto::SignFromKey, crypto::VerifyFromKey, errors::Error, log,
3};
4use rsa::pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey};
5use rsa::pkcs1v15::Signature;
6use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey};
7use rsa::sha2::{Sha256, Sha384, Sha512};
8use rsa::signature::{RandomizedSigner, SignatureEncoding, SignerMut, Verifier};
9
10#[derive(Debug)]
11pub struct RsaSigningKey {
12    key: rsa::RsaPrivateKey,
13}
14
15impl RsaSigningKey {
16    pub fn from_pem(key_str: &str) -> Result<Self, Error> {
17        let rsa_key = match key_str.starts_with("-----BEGIN RSA PRIVATE KEY-----") {
18            true => match rsa::RsaPrivateKey::from_pkcs1_pem(key_str) {
19                Ok(val) => val,
20                Err(error) => {
21                    log::error(error.to_string().as_str());
22                    return Err(Error::PRIVATE_KEY_IDENTIFICATION_ERROR);
23                }
24            },
25            false => match rsa::RsaPrivateKey::from_pkcs8_pem(key_str) {
26                Ok(val) => val,
27                Err(error) => {
28                    log::error(error.to_string().as_str());
29                    return Err(Error::PRIVATE_KEY_IDENTIFICATION_ERROR);
30                }
31            },
32        };
33
34        Ok(RsaSigningKey { key: rsa_key })
35    }
36}
37
38impl SignFromKey for RsaSigningKey {
39    fn sign(&self, message: String, alg: Algorithm) -> Result<String, Error> {
40        let key = self.key.clone();
41
42        let mut rng = rand::thread_rng();
43        if alg.to_str().starts_with("RS") {
44            let sig: Signature = match alg {
45                Algorithm::RS256 => {
46                    let mut signing_key = rsa::pkcs1v15::SigningKey::<Sha256>::new(key);
47                    signing_key.sign(message.as_bytes())
48                }
49                Algorithm::RS384 => {
50                    let mut signing_key = rsa::pkcs1v15::SigningKey::<Sha384>::new(key);
51                    signing_key.sign(message.as_bytes())
52                }
53                Algorithm::RS512 => {
54                    let mut signing_key = rsa::pkcs1v15::SigningKey::<Sha512>::new(key);
55                    signing_key.sign(message.as_bytes())
56                }
57                _ => return Err(Error::UNKNOWN_ALGORITHM),
58            };
59            let bytes = sig.to_bytes();
60            Ok(base64_url::encode(&bytes))
61        } else {
62            let sig = match alg {
63                Algorithm::PS256 => {
64                    let signing_key = rsa::pss::SigningKey::<Sha256>::new(key);
65                    signing_key.sign_with_rng(&mut rng, message.as_bytes())
66                }
67                Algorithm::PS384 => {
68                    let signing_key = rsa::pss::SigningKey::<Sha384>::new(key);
69                    signing_key.sign_with_rng(&mut rng, message.as_bytes())
70                }
71                Algorithm::PS512 => {
72                    let signing_key = rsa::pss::SigningKey::<Sha512>::new(key);
73                    signing_key.sign_with_rng(&mut rng, message.as_bytes())
74                }
75                _ => return Err(Error::UNKNOWN_ALGORITHM),
76            };
77
78            let bytes = sig.to_bytes();
79            Ok(base64_url::encode(&bytes))
80        }
81    }
82}
83
84#[derive(Debug)]
85pub struct RsaVerifyingKey {
86    key: rsa::RsaPublicKey,
87}
88
89impl RsaVerifyingKey {
90    pub fn from_pem(key_str: &str) -> Result<Self, Error> {
91        let rsa_key = match key_str.starts_with("-----BEGIN RSA PUBLIC KEY-----") {
92            true => match rsa::RsaPublicKey::from_pkcs1_pem(key_str) {
93                Ok(val) => val,
94                Err(error) => {
95                    log::error(error.to_string().as_str());
96                    return Err(Error::PRIVATE_KEY_IDENTIFICATION_ERROR);
97                }
98            },
99            false => match rsa::RsaPublicKey::from_public_key_pem(key_str) {
100                Ok(val) => val,
101                Err(error) => {
102                    log::error(error.to_string().as_str());
103                    return Err(Error::PRIVATE_KEY_IDENTIFICATION_ERROR);
104                }
105            },
106        };
107
108        Ok(RsaVerifyingKey { key: rsa_key })
109    }
110}
111
112impl VerifyFromKey for RsaVerifyingKey {
113    fn verify(&self, message: String, signature: String, alg: Algorithm) -> Result<bool, Error> {
114        let key = self.key.clone();
115
116        let decoded_sig_data = match base64_url::decode(&signature) {
117            Ok(val) => val,
118            Err(error) => {
119                log::error(error.to_string().as_str());
120                return Err(Error::DECODING_ERROR);
121            }
122        };
123
124        if alg.to_str().starts_with("RS") {
125            let sig = match rsa::pkcs1v15::Signature::try_from(decoded_sig_data.as_slice()) {
126                Ok(val) => val,
127                Err(error) => {
128                    log::error(error.to_string().as_str());
129                    return Err(Error::SIGNATURE_IDENTIFICATION_FAILED);
130                }
131            };
132
133            let verification = match alg {
134                Algorithm::RS256 => {
135                    let verifying_key = rsa::pkcs1v15::VerifyingKey::<Sha256>::new(key);
136                    verifying_key.verify(message.as_bytes(), &sig)
137                }
138                Algorithm::RS384 => {
139                    let verifying_key = rsa::pkcs1v15::VerifyingKey::<Sha384>::new(key);
140                    verifying_key.verify(message.as_bytes(), &sig)
141                }
142                Algorithm::RS512 => {
143                    let verifying_key = rsa::pkcs1v15::VerifyingKey::<Sha512>::new(key);
144                    verifying_key.verify(message.as_bytes(), &sig)
145                }
146                _ => return Err(Error::UNKNOWN_ALGORITHM),
147            };
148
149            if verification.is_ok() {
150                return Ok(true);
151            } else {
152                match verification.err() {
153                    Some(val) => {
154                        log::error(val.to_string().as_str());
155                    }
156                    None => {}
157                }
158                return Ok(false);
159            }
160        } else {
161            let sig = match rsa::pss::Signature::try_from(decoded_sig_data.as_slice()) {
162                Ok(val) => val,
163                Err(error) => {
164                    log::error(error.to_string().as_str());
165                    return Err(Error::SIGNATURE_IDENTIFICATION_FAILED);
166                }
167            };
168
169            let verification = match alg {
170                Algorithm::RS256 => {
171                    let verifying_key = rsa::pss::VerifyingKey::<Sha256>::new(key);
172                    verifying_key.verify(message.as_bytes(), &sig)
173                }
174                Algorithm::RS384 => {
175                    let verifying_key = rsa::pss::VerifyingKey::<Sha384>::new(key);
176                    verifying_key.verify(message.as_bytes(), &sig)
177                }
178                Algorithm::RS512 => {
179                    let verifying_key = rsa::pss::VerifyingKey::<Sha512>::new(key);
180                    verifying_key.verify(message.as_bytes(), &sig)
181                }
182                _ => return Err(Error::UNKNOWN_ALGORITHM),
183            };
184
185            if verification.is_ok() {
186                return Ok(true);
187            } else {
188                match verification.err() {
189                    Some(val) => {
190                        log::error(val.to_string().as_str());
191                    }
192                    None => {}
193                }
194                return Ok(false);
195            }
196        }
197    }
198}
199
200pub fn sign_rsa(message: String, key: impl SignFromKey, alg: Algorithm) -> Result<String, Error> {
201    key.sign(message, alg)
202}
203
204pub fn verify_rsa(
205    message: String,
206    signature: String,
207    key: impl VerifyFromKey,
208    alg: Algorithm,
209) -> Result<bool, Error> {
210    key.verify(message, signature, alg)
211}