steel_crypto/
signature.rs1use rsa::pkcs1v15::SigningKey;
6use rsa::sha2::Sha256;
7use rsa::signature::{SignatureEncoding, Signer as RsaSigner, Verifier};
8use rsa::{RsaPrivateKey, RsaPublicKey};
9use sha1::Sha1;
10
11use crate::rsa_utils::CryptError;
12
13pub trait SignatureUpdater {
17 fn update(&self, output: &mut dyn SignatureOutput) -> Result<(), CryptError>;
19}
20
21pub trait SignatureOutput {
25 fn update(&mut self, data: &[u8]) -> Result<(), CryptError>;
27}
28
29impl SignatureUpdater for &[u8] {
31 fn update(&self, output: &mut dyn SignatureOutput) -> Result<(), CryptError> {
32 output.update(self)
33 }
34}
35
36pub trait Signer {
40 fn sign(&self, updater: &dyn SignatureUpdater) -> Result<Vec<u8>, CryptError>;
42}
43
44pub trait SignatureValidator {
48 fn validate(
50 &self,
51 updater: &dyn SignatureUpdater,
52 signature: &[u8],
53 ) -> Result<bool, CryptError>;
54}
55
56pub struct RsaPrivateKeySigner {
60 signing_key: SigningKey<Sha256>,
61}
62
63impl RsaPrivateKeySigner {
64 #[must_use]
65 pub fn new(private_key: RsaPrivateKey) -> Self {
66 Self {
67 signing_key: SigningKey::new(private_key),
68 }
69 }
70}
71
72impl Signer for RsaPrivateKeySigner {
73 fn sign(&self, updater: &dyn SignatureUpdater) -> Result<Vec<u8>, CryptError> {
74 let mut collector = ByteCollector::new();
76 updater.update(&mut collector)?;
77
78 let signature = self.signing_key.sign(&collector.bytes);
80 Ok(signature.to_bytes().as_ref().to_vec())
81 }
82}
83
84pub struct RsaPublicKeyValidator {
88 verifying_key: rsa::pkcs1v15::VerifyingKey<Sha256>,
89}
90
91impl RsaPublicKeyValidator {
92 #[must_use]
93 pub fn new(public_key: RsaPublicKey) -> Self {
94 Self {
95 verifying_key: rsa::pkcs1v15::VerifyingKey::new(public_key),
96 }
97 }
98}
99
100impl SignatureValidator for RsaPublicKeyValidator {
101 fn validate(
102 &self,
103 updater: &dyn SignatureUpdater,
104 signature_bytes: &[u8],
105 ) -> Result<bool, CryptError> {
106 let mut collector = ByteCollector::new();
108 updater.update(&mut collector)?;
109
110 let signature = match rsa::pkcs1v15::Signature::try_from(signature_bytes) {
112 Ok(sig) => sig,
113 Err(_) => return Ok(false),
114 };
115
116 Ok(self
118 .verifying_key
119 .verify(&collector.bytes, &signature)
120 .is_ok())
121 }
122}
123
124pub struct ProfileKeyValidator {
129 validators: Vec<rsa::pkcs1v15::VerifyingKey<Sha1>>,
130}
131
132impl ProfileKeyValidator {
133 #[must_use]
135 pub fn new(public_keys: Vec<RsaPublicKey>) -> Option<Self> {
136 if public_keys.is_empty() {
137 return None;
138 }
139
140 Some(Self {
141 validators: public_keys
142 .into_iter()
143 .map(rsa::pkcs1v15::VerifyingKey::<Sha1>::new)
144 .collect(),
145 })
146 }
147}
148
149impl SignatureValidator for ProfileKeyValidator {
150 fn validate(
151 &self,
152 updater: &dyn SignatureUpdater,
153 signature: &[u8],
154 ) -> Result<bool, CryptError> {
155 let mut collector = ByteCollector::new();
156 updater.update(&mut collector)?;
157 let Ok(signature) = rsa::pkcs1v15::Signature::try_from(signature) else {
158 return Ok(false);
159 };
160 Ok(self
161 .validators
162 .iter()
163 .any(|validator| validator.verify(&collector.bytes, &signature).is_ok()))
164 }
165}
166
167pub struct NoValidation;
171
172impl SignatureValidator for NoValidation {
173 fn validate(
174 &self,
175 _updater: &dyn SignatureUpdater,
176 _signature: &[u8],
177 ) -> Result<bool, CryptError> {
178 Ok(true)
179 }
180}
181
182struct ByteCollector {
184 bytes: Vec<u8>,
185}
186
187impl ByteCollector {
188 const fn new() -> Self {
189 Self { bytes: Vec::new() }
190 }
191}
192
193impl SignatureOutput for ByteCollector {
194 fn update(&mut self, data: &[u8]) -> Result<(), CryptError> {
195 self.bytes.extend_from_slice(data);
196 Ok(())
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203 use crate::rsa_utils::generate_key_pair;
204
205 struct TestUpdater {
206 data: Vec<u8>,
207 }
208
209 impl SignatureUpdater for TestUpdater {
210 fn update(&self, output: &mut dyn SignatureOutput) -> Result<(), CryptError> {
211 output.update(&self.data)
212 }
213 }
214
215 #[test]
216 fn test_sign_and_verify() {
217 let (private_key, public_key) = generate_key_pair().unwrap();
218
219 let signer = RsaPrivateKeySigner::new(private_key);
220 let validator = RsaPublicKeyValidator::new(public_key);
221
222 let data = b"Hello, signed chat!";
223 let updater = TestUpdater {
224 data: data.to_vec(),
225 };
226
227 let signature = signer.sign(&updater).unwrap();
228 assert_eq!(signature.len(), 128);
231
232 let is_valid = validator.validate(&updater, &signature).unwrap();
233 assert!(is_valid);
234 }
235
236 #[test]
237 fn test_invalid_signature() {
238 let (_, public_key) = generate_key_pair().unwrap();
239 let validator = RsaPublicKeyValidator::new(public_key);
240
241 let data = b"Hello, signed chat!";
242 let updater = TestUpdater {
243 data: data.to_vec(),
244 };
245
246 let bad_signature = vec![0u8; crate::SIGNATURE_BYTES];
247 let is_valid = validator.validate(&updater, &bad_signature).unwrap();
248 assert!(!is_valid);
249 }
250
251 #[test]
252 fn profile_key_validator_uses_sha1_service_signatures() {
253 let (private_key, public_key) = generate_key_pair().unwrap();
254 let signer = SigningKey::<Sha1>::new(private_key);
255 let chat_validator = RsaPublicKeyValidator::new(public_key.clone());
256 let validator = ProfileKeyValidator::new(vec![public_key]).unwrap();
257 let updater = TestUpdater {
258 data: b"profile key certificate".to_vec(),
259 };
260 let signature = signer.sign(&updater.data).to_bytes();
261
262 assert!(validator.validate(&updater, &signature).unwrap());
263 assert!(!chat_validator.validate(&updater, &signature).unwrap());
264
265 let tampered = TestUpdater {
266 data: b"different certificate".to_vec(),
267 };
268 assert!(!validator.validate(&tampered, &signature).unwrap());
269 }
270
271 #[test]
272 fn profile_key_validator_requires_service_keys() {
273 assert!(ProfileKeyValidator::new(Vec::new()).is_none());
274 }
275
276 #[test]
277 fn test_no_validation() {
278 let validator = NoValidation;
279 let data = b"Any data";
280 let updater = TestUpdater {
281 data: data.to_vec(),
282 };
283 let signature = vec![0u8; 10];
284
285 let is_valid = validator.validate(&updater, &signature).unwrap();
286 assert!(is_valid);
287 }
288}