Skip to main content

licenz_core/crypto/
rsa.rs

1//! RSA-SHA256 signature algorithm implementation.
2//!
3//! This module implements the `SignatureAlgorithm` trait for RSA with SHA-256,
4//! providing backward compatibility with existing RSA-signed licenses.
5
6use super::SignatureAlgorithm;
7use crate::error::{LicenseError, Result};
8use pem::{encode, Pem};
9use rand::rngs::OsRng;
10use rsa::pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey};
11use rsa::pkcs1v15::{SigningKey, VerifyingKey};
12use rsa::pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey};
13use rsa::signature::{RandomizedSigner, SignatureEncoding, Verifier};
14use rsa::{RsaPrivateKey, RsaPublicKey};
15use sha2::Sha256;
16
17/// Default RSA key size in bits
18pub const DEFAULT_KEY_SIZE: usize = 3072;
19
20/// Supported RSA key sizes
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
22pub enum RsaKeySize {
23    Bits2048,
24    #[default]
25    Bits3072,
26    Bits4096,
27}
28
29impl RsaKeySize {
30    pub fn bits(&self) -> usize {
31        match self {
32            RsaKeySize::Bits2048 => 2048,
33            RsaKeySize::Bits3072 => 3072,
34            RsaKeySize::Bits4096 => 4096,
35        }
36    }
37}
38
39/// RSA-SHA256 signature algorithm implementation
40pub struct RsaSigner {
41    key_size: RsaKeySize,
42}
43
44impl Default for RsaSigner {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl RsaSigner {
51    /// Create a new RSA signer with default key size (2048 bits)
52    pub fn new() -> Self {
53        Self {
54            key_size: RsaKeySize::default(),
55        }
56    }
57
58    /// Create a new RSA signer with a specific key size
59    pub fn with_key_size(key_size: RsaKeySize) -> Self {
60        Self { key_size }
61    }
62
63    /// Parse a private key from PEM format
64    fn parse_private_key(pem_str: &str) -> Result<RsaPrivateKey> {
65        // Handle escaped newlines (from LDFLAGS injection)
66        let pem_str = pem_str.replace("\\n", "\n");
67
68        // Try PKCS#8 format first
69        if let Ok(key) = RsaPrivateKey::from_pkcs8_pem(&pem_str) {
70            return Ok(key);
71        }
72
73        // Try PKCS#1 format
74        if let Ok(key) = RsaPrivateKey::from_pkcs1_pem(&pem_str) {
75            return Ok(key);
76        }
77
78        Err(LicenseError::InvalidKeyFormat(
79            "Could not parse RSA private key (tried PKCS#8 and PKCS#1 formats)".into(),
80        ))
81    }
82
83    /// Parse a public key from PEM format
84    fn parse_public_key(pem_str: &str) -> Result<RsaPublicKey> {
85        // Handle escaped newlines (from LDFLAGS injection or env vars)
86        let pem_str = pem_str.replace("\\n", "\n");
87
88        // Try SPKI format first (most common)
89        if let Ok(key) = RsaPublicKey::from_public_key_pem(&pem_str) {
90            return Ok(key);
91        }
92
93        // Try PKCS#1 format
94        if let Ok(key) = RsaPublicKey::from_pkcs1_pem(&pem_str) {
95            return Ok(key);
96        }
97
98        Err(LicenseError::InvalidKeyFormat(
99            "Could not parse RSA public key (tried SPKI and PKCS#1 formats)".into(),
100        ))
101    }
102}
103
104impl SignatureAlgorithm for RsaSigner {
105    fn algorithm_id(&self) -> &'static str {
106        super::algorithm_ids::RSA_SHA256
107    }
108
109    fn sign(&self, data: &[u8], private_key_pem: &str) -> Result<Vec<u8>> {
110        let private_key = Self::parse_private_key(private_key_pem)?;
111        let signing_key = SigningKey::<Sha256>::new(private_key);
112        let mut rng = OsRng;
113
114        let signature = signing_key.sign_with_rng(&mut rng, data);
115        Ok(signature.to_bytes().to_vec())
116    }
117
118    fn verify(&self, data: &[u8], signature: &[u8], public_key_pem: &str) -> Result<()> {
119        let public_key = Self::parse_public_key(public_key_pem)?;
120        let verifying_key = VerifyingKey::<Sha256>::new(public_key);
121
122        let sig = rsa::pkcs1v15::Signature::try_from(signature).map_err(|e| {
123            LicenseError::VerificationFailed(format!("Invalid RSA signature format: {}", e))
124        })?;
125
126        verifying_key.verify(data, &sig).map_err(|e| {
127            LicenseError::VerificationFailed(format!("RSA signature verification failed: {}", e))
128        })
129    }
130
131    fn generate_keypair(&self) -> Result<(String, String)> {
132        let mut rng = OsRng;
133        let private_key = RsaPrivateKey::new(&mut rng, self.key_size.bits())
134            .map_err(|e| LicenseError::KeyGenerationFailed(e.to_string()))?;
135        let public_key = RsaPublicKey::from(&private_key);
136
137        let private_der = private_key
138            .to_pkcs8_der()
139            .map_err(|e| LicenseError::InvalidKeyFormat(e.to_string()))?;
140        let public_der = public_key
141            .to_public_key_der()
142            .map_err(|e| LicenseError::InvalidKeyFormat(e.to_string()))?;
143
144        let private_pem = encode(&Pem::new("PRIVATE KEY", private_der.as_bytes()));
145        let public_pem = encode(&Pem::new("PUBLIC KEY", public_der.as_bytes()));
146
147        Ok((private_pem, public_pem))
148    }
149
150    fn extract_public_key(&self, private_key_pem: &str) -> Result<String> {
151        let private_key = Self::parse_private_key(private_key_pem)?;
152        let public_key = RsaPublicKey::from(&private_key);
153
154        let public_der = public_key
155            .to_public_key_der()
156            .map_err(|e| LicenseError::InvalidKeyFormat(e.to_string()))?;
157        let public_pem = encode(&Pem::new("PUBLIC KEY", public_der.as_bytes()));
158
159        Ok(public_pem)
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn test_rsa_signer_algorithm_id() {
169        let signer = RsaSigner::new();
170        assert_eq!(signer.algorithm_id(), "RSA-SHA256");
171    }
172
173    #[test]
174    fn test_rsa_generate_keypair() {
175        let signer = RsaSigner::new();
176        let (private_pem, public_pem) = signer.generate_keypair().unwrap();
177
178        assert!(private_pem.contains("PRIVATE KEY"));
179        assert!(public_pem.contains("PUBLIC KEY"));
180    }
181
182    #[test]
183    fn test_rsa_sign_and_verify() {
184        let signer = RsaSigner::new();
185        let (private_pem, public_pem) = signer.generate_keypair().unwrap();
186
187        let data = b"Hello, World!";
188        let signature = signer.sign(data, &private_pem).unwrap();
189
190        assert!(!signature.is_empty());
191        assert!(signer.verify(data, &signature, &public_pem).is_ok());
192    }
193
194    #[test]
195    fn test_rsa_verify_wrong_data() {
196        let signer = RsaSigner::new();
197        let (private_pem, public_pem) = signer.generate_keypair().unwrap();
198
199        let data = b"Hello, World!";
200        let wrong_data = b"Goodbye, World!";
201        let signature = signer.sign(data, &private_pem).unwrap();
202
203        assert!(signer.verify(wrong_data, &signature, &public_pem).is_err());
204    }
205
206    #[test]
207    fn test_rsa_verify_wrong_key() {
208        let signer = RsaSigner::new();
209        let (private_pem, _) = signer.generate_keypair().unwrap();
210        let (_, other_public_pem) = signer.generate_keypair().unwrap();
211
212        let data = b"Hello, World!";
213        let signature = signer.sign(data, &private_pem).unwrap();
214
215        assert!(signer.verify(data, &signature, &other_public_pem).is_err());
216    }
217
218    #[test]
219    fn test_rsa_extract_public_key() {
220        let signer = RsaSigner::new();
221        let (private_pem, public_pem) = signer.generate_keypair().unwrap();
222
223        let extracted = signer.extract_public_key(&private_pem).unwrap();
224        assert_eq!(extracted, public_pem);
225    }
226
227    #[test]
228    fn test_rsa_key_sizes() {
229        assert_eq!(RsaKeySize::Bits2048.bits(), 2048);
230        assert_eq!(RsaKeySize::Bits3072.bits(), 3072);
231        assert_eq!(RsaKeySize::Bits4096.bits(), 4096);
232    }
233
234    #[test]
235    fn test_rsa_with_custom_key_size() {
236        let signer = RsaSigner::with_key_size(RsaKeySize::Bits2048);
237        let (private_pem, public_pem) = signer.generate_keypair().unwrap();
238
239        let data = b"Test data";
240        let signature = signer.sign(data, &private_pem).unwrap();
241        assert!(signer.verify(data, &signature, &public_pem).is_ok());
242    }
243}