Skip to main content

cas_lib/asymmetric/
cas_rsa.rs

1use rand::rngs::OsRng;
2use rsa::{
3    pkcs1::{DecodeRsaPublicKey, EncodeRsaPublicKey},
4    pkcs8::{DecodePrivateKey, EncodePrivateKey},
5    RsaPublicKey,
6};
7use rsa::{Pkcs1v15Sign, RsaPrivateKey};
8
9use crate::error::{CasError, CasResult};
10
11use super::types::{CASRSAEncryption, RSAKeyPairResult};
12
13/// The smallest RSA modulus size (in bits) this library will generate.
14/// Keys below 2048 bits are considered insecure.
15const MIN_RSA_KEY_SIZE: usize = 2048;
16
17pub struct CASRSA;
18
19impl CASRSAEncryption for CASRSA {
20    /// Generates an RSA key pair of the specified size.
21    /// The key size must be at least 2048 bits; smaller sizes are rejected with
22    /// [`CasError::InvalidParameters`].
23    fn generate_rsa_keys(key_size: usize) -> CasResult<RSAKeyPairResult> {
24        if key_size < MIN_RSA_KEY_SIZE {
25            return Err(CasError::InvalidParameters);
26        }
27        if key_size != 2048 && key_size != 3072 && key_size != 4096 {
28            return Err(CasError::InvalidParameters);
29        }
30        let mut rng: OsRng = OsRng;
31        let private_key: RsaPrivateKey =
32            RsaPrivateKey::new(&mut rng, key_size).map_err(|_| CasError::KeyGenerationFailed)?;
33        let public_key: RsaPublicKey = private_key.to_public_key();
34        Ok(RSAKeyPairResult {
35            public_key: public_key
36                .to_pkcs1_pem(rsa::pkcs1::LineEnding::LF)
37                .map_err(|_| CasError::InvalidPemKey)?
38                .to_string(),
39            private_key: private_key
40                .to_pkcs8_pem(rsa::pkcs8::LineEnding::LF)
41                .map_err(|_| CasError::InvalidPemKey)?
42                .to_string(),
43        })
44    }
45
46    /// Sign the given hash with the provided private key of the RSA key pair.
47    /// The parameter `hash` doesn't necessarily have to be a hash, it can be any data that you want to sign.
48    fn sign(private_key: String, hash: Vec<u8>) -> CasResult<Vec<u8>> {
49        let private_key =
50            RsaPrivateKey::from_pkcs8_pem(&private_key).map_err(|_| CasError::InvalidPemKey)?;
51        private_key
52            .sign(Pkcs1v15Sign::new_unprefixed(), &hash)
53            .map_err(|_| CasError::SigningFailed)
54    }
55
56
57    /// Verify the signature of the given hash with the provided public key of the RSA key pair.
58    /// The parameter `hash` doesn't necessarily have to be a hash, it can be any data that you want to verify.
59    /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if it is not, and an
60    /// error if the public key could not be parsed.
61    fn verify(public_key: String, hash: Vec<u8>, signature: Vec<u8>) -> CasResult<bool> {
62        let public_key =
63            RsaPublicKey::from_pkcs1_pem(&public_key).map_err(|_| CasError::InvalidPemKey)?;
64        Ok(public_key
65            .verify(Pkcs1v15Sign::new_unprefixed(), &hash, &signature)
66            .is_ok())
67    }
68}