1#[macro_use]
34extern crate error_chain;
35
36use aes::cipher::generic_array::GenericArray;
37use base64::{engine::general_purpose::STANDARD as base64, Engine as _};
38use digest::CtOutput;
39use pbkdf2::{
40 hmac::{Hmac, Mac},
41 pbkdf2_hmac,
42};
43use rand::RngCore;
44use sha1::Sha1;
45use subtle::ConstantTimeEq;
46
47error_chain! {
48 foreign_links {
49 DecodeBase64(base64::DecodeError);
50 InvalidLength(digest::InvalidLength);
51 }
52
53 errors {
54 InvalidSignature {
55 description("Invalid message signature")
56 }
57
58 InvalidMessage {
59 description("Invalid message encoding or format")
60 }
61
62 KeyDerivationFailure {
63 description("Key Derivation Function failed to generate one or more keys")
64 }
65 }
66}
67
68pub struct Verifier {
70 secret_key: Vec<u8>,
71}
72
73pub enum KeySize {
75 Aes128,
76 Aes192,
77 Aes256,
78}
79
80pub trait Encryptor {
83 fn decrypt_and_verify(&self, message: &str) -> Result<Vec<u8>>;
84 fn encrypt_and_sign(&self, message: &str) -> Result<String>;
85}
86
87pub struct AesHmacEncryptor {
89 pub key_size: KeySize,
90 secret_key: Vec<u8>,
91 verifier: Verifier,
92}
93
94pub struct AesGcmEncryptor {
96 pub key_size: KeySize,
97 secret_key: Vec<u8>,
98}
99
100pub struct DerivedKeyParams {
102 size: u32,
103 iterations: u32,
104}
105
106impl Default for DerivedKeyParams {
107 fn default() -> DerivedKeyParams {
112 DerivedKeyParams {
113 size: 64,
114 iterations: 1000,
115 }
116 }
117}
118
119pub fn create_derived_keys(
122 salts: &[&str],
123 secret: &str,
124 key_params: DerivedKeyParams,
125) -> Vec<Vec<u8>> {
126 salts
127 .iter()
128 .map(|salt| {
129 let mut result: Vec<u8> = vec![0; key_params.size as usize];
130 pbkdf2_hmac::<Sha1>(
131 secret.as_bytes(),
132 salt.as_bytes(),
133 key_params.iterations,
134 &mut result,
135 );
136 result
137 })
138 .collect()
139}
140
141fn random_iv(sz: usize) -> Vec<u8> {
142 let mut rng = rand::thread_rng();
143 let mut buffer: Vec<u8> = vec![0; sz];
144 rng.fill_bytes(&mut buffer);
145 buffer
146}
147
148fn split_by_n_dashes(n: usize, message: &str) -> Result<Vec<&str>> {
149 let split: Vec<&str> = message.splitn(n, "--").collect();
150
151 if split.len() == n {
152 Ok(split)
153 } else {
154 bail!(ErrorKind::InvalidMessage)
155 }
156}
157
158fn split_by_n_dashes_from_u8_slice(n: usize, slice: &[u8]) -> Result<Vec<&str>> {
159 match std::str::from_utf8(slice) {
160 Ok(string) => split_by_n_dashes(n, string),
161 Err(_) => bail!(ErrorKind::InvalidMessage),
162 }
163}
164
165impl Verifier {
166 pub fn new(secret: &str) -> Verifier {
168 Verifier {
169 secret_key: secret.bytes().collect(),
170 }
171 }
172
173 pub fn verify(&self, message: &str) -> Result<Vec<u8>> {
175 let msg_split = split_by_n_dashes(2, message)?;
176
177 let encoded_data = msg_split[0];
178 let signature = msg_split[1];
179
180 match self.is_valid_message(encoded_data, signature)? {
181 true => Ok(base64.decode(encoded_data)?),
182 false => bail!(ErrorKind::InvalidSignature),
183 }
184 }
185
186 pub fn is_valid_message(&self, encoded_data: &str, signature: &str) -> Result<bool> {
188 match hex::decode(signature) {
189 Ok(sig_bytes) => {
190 let mut mac = Hmac::<Sha1>::new_from_slice(&self.secret_key)?;
191 mac.update(encoded_data.as_bytes());
192 let sig = CtOutput::new(GenericArray::clone_from_slice(sig_bytes.as_slice()));
193 Ok(mac.finalize().ct_eq(&sig).into())
194 }
195
196 Err(_) => Ok(false),
197 }
198 }
199
200 pub fn generate(&self, message: &str) -> Result<String> {
203 let mut mac = Hmac::<Sha1>::new_from_slice(&self.secret_key)?;
204 let encoded_data = base64.encode(message.as_bytes());
205
206 mac.update(encoded_data.as_bytes());
207
208 let signature = mac.finalize();
209 let result = format!("{}--{}", encoded_data, hex::encode(signature.into_bytes()));
210
211 Ok(result.clone())
212 }
213}
214
215impl AesHmacEncryptor {
216 pub fn new(
218 secret: &str,
219 salt: &str,
220 sign_salt: &str,
221 key_params: DerivedKeyParams,
222 ) -> Result<AesHmacEncryptor> {
223 let salts = vec![salt, sign_salt];
224 let keys = create_derived_keys(&salts, secret, key_params);
225
226 match (keys.first(), keys.last()) {
227 (Some(cipher_key), Some(sig_key)) => Ok(AesHmacEncryptor {
228 key_size: KeySize::Aes256,
229 secret_key: cipher_key.to_vec(),
230 verifier: Verifier {
231 secret_key: sig_key.to_vec(),
232 },
233 }),
234
235 _ => bail!(ErrorKind::KeyDerivationFailure),
236 }
237 }
238}
239
240impl Encryptor for AesHmacEncryptor {
241 fn decrypt_and_verify(&self, message: &str) -> Result<Vec<u8>> {
244 let decoded = self.verifier.verify(message)?;
245 let msg_split = split_by_n_dashes_from_u8_slice(2, &decoded)?;
246
247 let cipher_text = base64.decode(msg_split[0])?;
248 let iv = base64.decode(msg_split[1])?;
249
250 use aes::cipher::{block_padding::Pkcs7, BlockDecryptMut, KeyIvInit};
251
252 match self.key_size {
253 KeySize::Aes128 => {
254 cbc::Decryptor::<aes::Aes128>::new_from_slices(&self.secret_key[0..16], &iv)?
255 .decrypt_padded_vec_mut::<Pkcs7>(&cipher_text)
256 }
257 KeySize::Aes192 => {
258 cbc::Decryptor::<aes::Aes192>::new_from_slices(&self.secret_key[0..24], &iv)?
259 .decrypt_padded_vec_mut::<Pkcs7>(&cipher_text)
260 }
261 KeySize::Aes256 => {
262 cbc::Decryptor::<aes::Aes256>::new_from_slices(&self.secret_key[0..32], &iv)?
263 .decrypt_padded_vec_mut::<Pkcs7>(&cipher_text)
264 }
265 }
266 .or(Err(ErrorKind::InvalidMessage.into()))
267 }
268
269 fn encrypt_and_sign(&self, message: &str) -> Result<String> {
272 let iv = random_iv(16);
273 let message = message.as_bytes();
274
275 use aes::cipher::{block_padding::Pkcs7, BlockEncryptMut, KeyIvInit};
276
277 let cipher_result = match self.key_size {
278 KeySize::Aes128 => {
279 cbc::Encryptor::<aes::Aes128>::new_from_slices(&self.secret_key[0..16], &iv)?
280 .encrypt_padded_vec_mut::<Pkcs7>(message)
281 }
282 KeySize::Aes192 => {
283 cbc::Encryptor::<aes::Aes192>::new_from_slices(&self.secret_key[0..24], &iv)?
284 .encrypt_padded_vec_mut::<Pkcs7>(message)
285 }
286 KeySize::Aes256 => {
287 cbc::Encryptor::<aes::Aes256>::new_from_slices(&self.secret_key[0..32], &iv)?
288 .encrypt_padded_vec_mut::<Pkcs7>(message)
289 }
290 };
291
292 let encoded_ctxt = base64.encode(cipher_result);
293 let encoded_iv = base64.encode(iv);
294
295 self.verifier
296 .generate(&format!("{}--{}", encoded_ctxt, encoded_iv))
297 }
298}
299
300impl AesGcmEncryptor {
301 pub fn new(secret: &str, salt: &str, key_params: DerivedKeyParams) -> Result<AesGcmEncryptor> {
303 let salts = vec![salt];
304 let keys = create_derived_keys(&salts, secret, key_params);
305
306 match keys.first() {
307 Some(cipher_key) => Ok(AesGcmEncryptor {
308 key_size: KeySize::Aes256,
309 secret_key: cipher_key.to_vec(),
310 }),
311
312 _ => bail!(ErrorKind::KeyDerivationFailure),
313 }
314 }
315}
316
317impl Encryptor for AesGcmEncryptor {
318 fn decrypt_and_verify(&self, message: &str) -> Result<Vec<u8>> {
321 let msg_split = split_by_n_dashes(3, message)?;
322
323 let mut cipher_text = base64.decode(msg_split[0])?;
324 let iv = GenericArray::clone_from_slice(&base64.decode(msg_split[1])?);
325 let auth_tag = GenericArray::clone_from_slice(&base64.decode(msg_split[2])?);
326
327 use aes_gcm::{aead::KeyInit, AeadInPlace, AesGcm};
328 use digest::consts::U12;
329
330 let result = match self.key_size {
331 KeySize::Aes128 => {
332 let cipher = AesGcm::<aes::Aes128, U12>::new_from_slice(&self.secret_key[0..16])?;
333 cipher.decrypt_in_place_detached(&iv, &[], &mut cipher_text, &auth_tag)
334 }
335 KeySize::Aes192 => {
336 let cipher = AesGcm::<aes::Aes192, U12>::new_from_slice(&self.secret_key[0..24])?;
337 cipher.decrypt_in_place_detached(&iv, &[], &mut cipher_text, &auth_tag)
338 }
339 KeySize::Aes256 => {
340 let cipher = AesGcm::<aes::Aes256, U12>::new_from_slice(&self.secret_key[0..32])?;
341 cipher.decrypt_in_place_detached(&iv, &[], &mut cipher_text, &auth_tag)
342 }
343 };
344 if result.is_err() {
345 bail!(ErrorKind::InvalidMessage);
346 }
347 Ok(cipher_text)
348 }
349
350 fn encrypt_and_sign(&self, message: &str) -> Result<String> {
353 let random_iv = GenericArray::clone_from_slice(&random_iv(12));
354
355 use aes_gcm::{aead::KeyInit, AeadInPlace, AesGcm};
356 use digest::consts::U12;
357
358 let mut output: Vec<u8> = message.as_bytes().to_vec();
359 let auth_tag = match self.key_size {
360 KeySize::Aes128 => {
361 let cipher = AesGcm::<aes::Aes128, U12>::new_from_slice(&self.secret_key[0..16])?;
362 cipher.encrypt_in_place_detached(&random_iv, &[], &mut output)
363 }
364 KeySize::Aes192 => {
365 let cipher = AesGcm::<aes::Aes192, U12>::new_from_slice(&self.secret_key[0..24])?;
366 cipher.encrypt_in_place_detached(&random_iv, &[], &mut output)
367 }
368 KeySize::Aes256 => {
369 let cipher = AesGcm::<aes::Aes256, U12>::new_from_slice(&self.secret_key[0..32])?;
370 cipher.encrypt_in_place_detached(&random_iv, &[], &mut output)
371 }
372 };
373 let Ok(auth_tag) = auth_tag else {
374 bail!(ErrorKind::InvalidMessage);
375 };
376
377 let encoded_ctxt = base64.encode(output);
378 let encoded_iv = base64.encode(random_iv);
379 let encoded_tag = base64.encode(auth_tag);
380 Ok(format!("{}--{}--{}", encoded_ctxt, encoded_iv, encoded_tag))
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 macro_rules! assert_error_kind {
388 ($err:expr, $kind:pat) => {
389 match *$err.kind() {
390 $kind => assert!(true, "{:?} is of kind {:?}", $err, stringify!($kind)),
391 _ => assert!(false, "{:?} is NOT of kind {:?}", $err, stringify!($kind)),
392 }
393 };
394 }
395
396 use crate::*;
397
398 #[test]
399 fn is_valid_message_returns_true_for_valid_signatures() {
400 let data = "eyJrZXkiOiJ2YWx1ZSJ9";
401 let sig = "fa115453dbb4a28277b1ba07ef4c7437621f5d72";
402
403 let verifier = Verifier::new("helloworld");
404
405 assert!(verifier.is_valid_message(data, sig).unwrap());
406 }
407
408 #[test]
409 fn is_valid_message_returns_false_for_invalid_signatures() {
410 let data = "eyJrZXkiOiJ2YWx1ZSJ9";
411 let sig = "05330518df0e21fb9beec7a71a5f5f951c3f5254";
412
413 let verifier = Verifier::new("helloworld");
414
415 assert!(!verifier.is_valid_message(data, sig).unwrap());
416 }
417
418 #[test]
419 fn is_valid_message_returns_false_for_invalid_messages() {
420 let data = "baddata";
421 let sig = "badsig";
422
423 let verifier = Verifier::new("helloworld");
424
425 assert!(!verifier.is_valid_message(data, sig).unwrap());
426 }
427
428 #[test]
429 fn verify_returns_decoded_message_for_valid_signatures() {
430 let msg = "eyJrZXkiOiJ2YWx1ZSJ9--fa115453dbb4a28277b1ba07ef4c7437621f5d72";
431
432 let verifier = Verifier::new("helloworld");
433
434 assert_eq!(
435 verifier.verify(msg).unwrap(),
436 "{\"key\":\"value\"}".as_bytes()
437 );
438 }
439
440 #[test]
441 fn verify_returns_invalid_signature_error_for_wrong_key() {
442 let msg = "eyJrZXkiOiJ2YWx1ZSJ9--05330518df0e21fb9beec7a71a5f5f951c3f5254";
443
444 let verifier = Verifier::new("helloworld");
445
446 assert_error_kind!(
447 verifier.verify(msg).unwrap_err(),
448 ErrorKind::InvalidSignature
449 );
450 }
451
452 #[test]
453 fn verify_returns_invalid_message_error_for_empty_message() {
454 let msg = "";
455
456 let verifier = Verifier::new("helloworld");
457
458 assert_error_kind!(verifier.verify(msg).unwrap_err(), ErrorKind::InvalidMessage);
459 }
460
461 #[test]
462 fn generate_returns_signed_and_encoded_string() {
463 let verifier = Verifier::new("helloworld");
464 let expected = "eyJrZXkiOiJ2YWx1ZSJ9--fa115453dbb4a28277b1ba07ef4c7437621f5d72";
465
466 assert_eq!(
467 verifier.generate("{\"key\":\"value\"}").unwrap(),
468 expected.to_string()
469 );
470 }
471
472 #[test]
473 fn aes_hamc_decrypt_and_verify_returns_decoded_message_for_valid_messages() {
474 let msg = "c20wSnp6Z1o1U2MyWDVjU3BPeWNNQT09LS1JOWNyR25LdDRpZUUvcmoxVTdoSTNRPT0=--a79c9522355e55bf8e4302c66d8bf5638f1a50ec";
475
476 let dkp = DerivedKeyParams::default();
477 let encryptor =
478 AesHmacEncryptor::new("helloworld", "test salt", "test signed salt", dkp).unwrap();
479
480 assert_eq!(
481 encryptor.decrypt_and_verify(msg).unwrap(),
482 "{\"key\":\"value\"}".as_bytes()
483 );
484 }
485
486 #[test]
487 fn aes_hamc_decrypt_and_verify_returns_invalid_signature_error_for_wrong_key() {
488 let msg = "SnRXQXFhOE9WSGg2QmVGUDdHdkhNZz09LS1vcjFWcm53VU40YmV0SVcwdWFlK2NRPT0=--c879b51cbd92559d4d684c406b3aaebfbc958e9d";
489
490 let dkp = DerivedKeyParams::default();
491 let encryptor =
492 AesHmacEncryptor::new("helloworld", "test salt", "test signed salt", dkp).unwrap();
493
494 assert_error_kind!(
495 encryptor.decrypt_and_verify(msg).unwrap_err(),
496 ErrorKind::InvalidSignature
497 );
498 }
499
500 #[test]
501 fn aes_hamc_decrypt_and_verify_returns_invalid_message_for_empty_message() {
502 let msg = "";
503
504 let dkp = DerivedKeyParams::default();
505 let encryptor =
506 AesHmacEncryptor::new("helloworld", "test salt", "test signed salt", dkp).unwrap();
507
508 assert_error_kind!(
509 encryptor.decrypt_and_verify(msg).unwrap_err(),
510 ErrorKind::InvalidMessage
511 );
512 }
513
514 #[test]
515 fn aes_hamc_encrypt_and_sign_returns_encrypted_and_signed_decryptable_and_verifiable_string() {
516 let dkp = DerivedKeyParams::default();
517 let encryptor =
518 AesHmacEncryptor::new("helloworld", "test salt", "test signed salt", dkp).unwrap();
519
520 let message = encryptor.encrypt_and_sign("{\"key\":\"value\"}").unwrap();
521
522 assert_eq!(
523 encryptor.decrypt_and_verify(&message).unwrap(),
524 "{\"key\":\"value\"}".as_bytes()
525 );
526 }
527
528 #[test]
529 fn aes_hamc_decrypt_and_verify_returns_decoded_message_with_non_default_cipher_for_valid_messages(
530 ) {
531 let msg = "RXFQajB4VzR3QytRQ0NpQXlGUFFTdz09LS0ycUZlcWFXNlRsb1phanMvcHlwVCtRPT0=--5d4739f859e1f730dc0ae7abfb21160c9f00dae6";
532
533 let dkp = DerivedKeyParams::default();
534 let mut encryptor =
535 AesHmacEncryptor::new("helloworld", "test salt", "test signed salt", dkp).unwrap();
536 encryptor.key_size = KeySize::Aes192;
537
538 assert_eq!(
539 encryptor.decrypt_and_verify(msg).unwrap(),
540 "{\"key\":\"value\"}".as_bytes()
541 );
542 }
543
544 #[test]
545 fn aes_hamc_encrypt_and_sign_returns_encrypted_and_signed_decryptable_and_verifiable_string_with_non_default_cipher(
546 ) {
547 let dkp = DerivedKeyParams::default();
548 let mut encryptor =
549 AesHmacEncryptor::new("helloworld", "test salt", "test signed salt", dkp).unwrap();
550 encryptor.key_size = KeySize::Aes192;
551
552 let message = encryptor.encrypt_and_sign("{\"key\":\"value\"}").unwrap();
553
554 assert_eq!(
555 encryptor.decrypt_and_verify(&message).unwrap(),
556 "{\"key\":\"value\"}".as_bytes()
557 );
558 }
559
560 #[test]
561 fn aes_gcm_decrypt_and_verify_returns_decoded_message_for_valid_messages() {
562 let msg = "H9msESjs5e8I6utXGnk0--4UI1B/xoA1MIR3A3--DHpzaZ7LMhFsWXzEbLiOCA==";
563
564 let dkp = DerivedKeyParams::default();
565 let encryptor = AesGcmEncryptor::new("helloworld", "test salt", dkp).unwrap();
566
567 assert_eq!(
568 encryptor.decrypt_and_verify(msg).unwrap(),
569 "{\"key\":\"value\"}".as_bytes()
570 );
571 }
572
573 #[test]
574 fn aes_gcm_decrypt_and_verify_returns_invalid_message_error_for_wrong_key() {
575 let msg = "Rhlx3KvutaC3AU1gi7pg--5T4OYITxIw56qdfL--pcc0hZjYYP/5xgTRYFqnkA==";
576
577 let dkp = DerivedKeyParams::default();
578 let encryptor = AesGcmEncryptor::new("helloworld", "test salt", dkp).unwrap();
579
580 assert_error_kind!(
581 encryptor.decrypt_and_verify(msg).unwrap_err(),
582 ErrorKind::InvalidMessage
583 );
584 }
585
586 #[test]
587 fn aes_gcm_decrypt_and_verify_returns_invalid_message_for_empty_message() {
588 let msg = "";
589
590 let dkp = DerivedKeyParams::default();
591 let encryptor = AesGcmEncryptor::new("helloworld", "test signed salt", dkp).unwrap();
592
593 assert_error_kind!(
594 encryptor.decrypt_and_verify(msg).unwrap_err(),
595 ErrorKind::InvalidMessage
596 );
597 }
598
599 #[test]
600 fn aes_gcm_encrypt_and_sign_returns_encrypted_and_signed_decryptable_and_verifiable_string() {
601 let dkp = DerivedKeyParams::default();
602 let encryptor = AesGcmEncryptor::new("helloworld", "test salt", dkp).unwrap();
603
604 let message = encryptor.encrypt_and_sign("{\"key\":\"value\"}").unwrap();
605
606 assert_eq!(
607 encryptor.decrypt_and_verify(&message).unwrap(),
608 "{\"key\":\"value\"}".as_bytes()
609 );
610 }
611}