1mod ciphertext_v1;
44mod ciphertext_v2;
45
46use super::CiphertextSubtype;
47pub use super::CiphertextVersion;
48use super::DataType;
49use super::Error;
50use super::Header;
51use super::HeaderType;
52use super::Result;
53
54use super::key::{PrivateKey, PublicKey, SecretKey};
55
56use ciphertext_v1::CiphertextV1;
57use ciphertext_v2::{CiphertextV2Asymmetric, CiphertextV2Symmetric};
58
59use std::borrow::Borrow;
60use std::convert::TryFrom;
61
62#[cfg(feature = "fuzz")]
63use arbitrary::Arbitrary;
64
65#[derive(Clone, Debug)]
67#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
68pub struct Ciphertext {
69 pub(crate) header: Header<Ciphertext>,
70 payload: CiphertextPayload,
71}
72
73impl HeaderType for Ciphertext {
74 type Version = CiphertextVersion;
75 type Subtype = CiphertextSubtype;
76
77 fn data_type() -> DataType {
78 DataType::Ciphertext
79 }
80}
81
82#[derive(Clone, Debug)]
83#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
84enum CiphertextPayload {
85 V1(CiphertextV1),
86 V2Symmetric(CiphertextV2Symmetric),
87 V2Asymmetric(CiphertextV2Asymmetric),
88}
89
90pub fn encrypt(data: &[u8], key: &[u8], version: CiphertextVersion) -> Result<Ciphertext> {
107 encrypt_with_raw_key(data, key, version)
108}
109
110pub fn encrypt_with_raw_key(
127 data: &[u8],
128 key: &[u8],
129 version: CiphertextVersion,
130) -> Result<Ciphertext> {
131 encrypt_with_aad(data, key, [].as_slice(), version)
132}
133
134pub fn encrypt_with_aad(
153 data: &[u8],
154 key: &[u8],
155 aad: &[u8],
156 version: CiphertextVersion,
157) -> Result<Ciphertext> {
158 let mut header = Header::default();
159
160 header.data_subtype = CiphertextSubtype::Symmetric;
161
162 let payload = match version {
163 CiphertextVersion::V1 => {
164 header.version = CiphertextVersion::V1;
165 CiphertextPayload::V1(CiphertextV1::encrypt(data, key, aad, &header)?)
166 }
167 CiphertextVersion::V2 | CiphertextVersion::Latest => {
168 header.version = CiphertextVersion::V2;
169 CiphertextPayload::V2Symmetric(CiphertextV2Symmetric::encrypt(data, key, aad, &header)?)
170 } };
172
173 Ok(Ciphertext { header, payload })
174}
175
176pub fn encrypt_asymmetric(
195 data: &[u8],
196 public_key: &PublicKey,
197 version: CiphertextVersion,
198) -> Result<Ciphertext> {
199 encrypt_asymmetric_with_aad(data, public_key, [].as_slice(), version)
200}
201
202pub fn encrypt_asymmetric_with_aad(
223 data: &[u8],
224 public_key: &PublicKey,
225 aad: &[u8],
226 version: CiphertextVersion,
227) -> Result<Ciphertext> {
228 let mut header = Header::default();
229
230 header.data_subtype = CiphertextSubtype::Asymmetric;
231
232 let payload = match version {
233 CiphertextVersion::V2 | CiphertextVersion::Latest => {
234 header.version = CiphertextVersion::V2;
235 CiphertextPayload::V2Asymmetric(CiphertextV2Asymmetric::encrypt(
236 data, public_key, aad, &header,
237 )?)
238 }
239 _ => return Err(Error::UnknownVersion),
240 };
241
242 Ok(Ciphertext { header, payload })
243}
244
245pub fn encrypt_with_secret_key(
263 data: &[u8],
264 key: &SecretKey,
265 version: CiphertextVersion,
266) -> Result<Ciphertext> {
267 encrypt(data, key.as_bytes(), version)
268}
269
270pub fn encrypt_with_secret_key_and_aad(
290 data: &[u8],
291 key: &SecretKey,
292 aad: &[u8],
293 version: CiphertextVersion,
294) -> Result<Ciphertext> {
295 encrypt_with_aad(data, key.as_bytes(), aad, version)
296}
297
298impl Ciphertext {
299 pub fn decrypt(&self, key: &[u8]) -> Result<Vec<u8>> {
317 self.decrypt_with_raw_key(key)
318 }
319
320 pub fn decrypt_with_raw_key(&self, key: &[u8]) -> Result<Vec<u8>> {
338 self.decrypt_with_aad(key, [].as_slice())
339 }
340
341 pub fn decrypt_with_aad(&self, key: &[u8], aad: &[u8]) -> Result<Vec<u8>> {
361 match &self.payload {
362 CiphertextPayload::V1(x) => x.decrypt(key, aad, &self.header),
363 CiphertextPayload::V2Symmetric(x) => x.decrypt(key, aad, &self.header),
364 _ => Err(Error::InvalidDataType),
365 }
366 }
367
368 pub fn decrypt_asymmetric(&self, private_key: &PrivateKey) -> Result<Vec<u8>> {
387 self.decrypt_asymmetric_with_aad(private_key, [].as_slice())
388 }
389
390 pub fn decrypt_asymmetric_with_aad(
411 &self,
412 private_key: &PrivateKey,
413 aad: &[u8],
414 ) -> Result<Vec<u8>> {
415 match &self.payload {
416 CiphertextPayload::V2Asymmetric(x) => x.decrypt(private_key, aad, &self.header),
417 CiphertextPayload::V1(_) => Err(Error::UnknownVersion),
418 _ => Err(Error::InvalidDataType),
419 }
420 }
421
422 pub fn decrypt_with_secret_key(&self, key: &SecretKey) -> Result<Vec<u8>> {
441 self.decrypt(key.as_bytes())
442 }
443
444 pub fn decrypt_with_secret_key_and_aad(&self, key: &SecretKey, aad: &[u8]) -> Result<Vec<u8>> {
465 self.decrypt_with_aad(key.as_bytes(), aad)
466 }
467}
468
469impl From<Ciphertext> for Vec<u8> {
470 fn from(data: Ciphertext) -> Self {
472 let mut header: Self = data.header.borrow().into();
473 let mut payload: Self = data.payload.into();
474 header.append(&mut payload);
475 header
476 }
477}
478
479impl TryFrom<&[u8]> for Ciphertext {
480 type Error = Error;
481
482 fn try_from(data: &[u8]) -> Result<Self> {
484 if data.len() < Header::len() {
485 return Err(Error::InvalidLength);
486 };
487
488 let header = Header::try_from(&data[0..Header::len()])?;
489
490 let payload = match header.version {
491 CiphertextVersion::V1 => {
492 CiphertextPayload::V1(CiphertextV1::try_from(&data[Header::len()..])?)
493 }
494 CiphertextVersion::V2 => match header.data_subtype {
495 CiphertextSubtype::Symmetric | CiphertextSubtype::None => {
496 CiphertextPayload::V2Symmetric(CiphertextV2Symmetric::try_from(
497 &data[Header::len()..],
498 )?)
499 }
500 CiphertextSubtype::Asymmetric => CiphertextPayload::V2Asymmetric(
501 CiphertextV2Asymmetric::try_from(&data[Header::len()..])?,
502 ),
503 },
504 _ => return Err(Error::UnknownVersion),
505 };
506
507 Ok(Self { header, payload })
508 }
509}
510
511impl From<CiphertextPayload> for Vec<u8> {
512 fn from(data: CiphertextPayload) -> Self {
513 match data {
514 CiphertextPayload::V1(x) => x.into(),
515 CiphertextPayload::V2Symmetric(x) => x.into(),
516 CiphertextPayload::V2Asymmetric(x) => x.into(),
517 }
518 }
519}
520
521#[test]
522fn encrypt_decrypt_test() {
523 let key = "0123456789abcdefghijkl".as_bytes();
524 let data = "This is a very complex string of character that we need to encrypt".as_bytes();
525
526 let encrypted = encrypt(data, key, CiphertextVersion::Latest).unwrap();
527
528 let encrypted: Vec<u8> = encrypted.into();
529
530 let encrypted = Ciphertext::try_from(encrypted.as_slice()).unwrap();
531 let decrypted = encrypted.decrypt(key).unwrap();
532
533 assert_eq!(decrypted, data);
534}
535
536#[test]
537fn encrypt_decrypt_aad_test() {
538 let key = b"0123456789abcdefghijkl";
539 let data = b"This is a very complex string of character that we need to encrypt";
540 let aad = b"This is some public data that we want to authenticate";
541 let wrong_aad = b"this is some public data that we want to authenticate";
542
543 let encrypted = encrypt_with_aad(data, key, aad, CiphertextVersion::Latest).unwrap();
544
545 let encrypted: Vec<u8> = encrypted.into();
546
547 let encrypted = Ciphertext::try_from(encrypted.as_slice()).unwrap();
548 let decrypted = encrypted.decrypt_with_aad(key, aad).unwrap();
549
550 assert_eq!(decrypted, data);
551
552 let decrypted = encrypted.decrypt_with_aad(key, wrong_aad);
553
554 assert!(decrypted.is_err());
555
556 let decrypted = encrypted.decrypt(key);
557
558 assert!(decrypted.is_err());
559}
560
561#[test]
562fn encrypt_decrypt_v1_test() {
563 let key = "0123456789abcdefghijkl".as_bytes();
564 let data = "This is a very complex string of character that we need to encrypt".as_bytes();
565
566 let encrypted = encrypt(data, key, CiphertextVersion::V1).unwrap();
567
568 assert_eq!(encrypted.header.version, CiphertextVersion::V1);
569 let encrypted: Vec<u8> = encrypted.into();
570
571 let encrypted = Ciphertext::try_from(encrypted.as_slice()).unwrap();
572 let decrypted = encrypted.decrypt(key).unwrap();
573
574 assert_eq!(decrypted, data);
575}
576
577#[test]
578fn encrypt_decrypt_aad_v1_test() {
579 let key = b"0123456789abcdefghijkl";
580 let data = b"This is a very complex string of character that we need to encrypt";
581 let aad = b"This is some public data that we want to authenticate";
582 let wrong_aad = b"this is some public data that we want to authenticate";
583
584 let encrypted = encrypt_with_aad(data, key, aad, CiphertextVersion::V1).unwrap();
585
586 let encrypted: Vec<u8> = encrypted.into();
587
588 let encrypted = Ciphertext::try_from(encrypted.as_slice()).unwrap();
589 let decrypted = encrypted.decrypt_with_aad(key, aad).unwrap();
590
591 assert_eq!(decrypted, data);
592
593 let decrypted = encrypted.decrypt_with_aad(key, wrong_aad);
594
595 assert!(decrypted.is_err());
596
597 let decrypted = encrypted.decrypt(key);
598
599 assert!(decrypted.is_err());
600}
601
602#[test]
603fn encrypt_decrypt_v2_test() {
604 let key = "0123456789abcdefghijkl".as_bytes();
605 let data = "This is a very complex string of character that we need to encrypt".as_bytes();
606
607 let encrypted = encrypt(data, key, CiphertextVersion::V2).unwrap();
608
609 assert_eq!(encrypted.header.version, CiphertextVersion::V2);
610 let encrypted: Vec<u8> = encrypted.into();
611
612 let encrypted = Ciphertext::try_from(encrypted.as_slice()).unwrap();
613 let decrypted = encrypted.decrypt(key).unwrap();
614
615 assert_eq!(decrypted, data);
616}
617
618#[test]
619fn encrypt_decrypt_aad_v2_test() {
620 let key = b"0123456789abcdefghijkl";
621 let data = b"This is a very complex string of character that we need to encrypt";
622 let aad = b"This is some public data that we want to authenticate";
623 let wrong_aad = b"this is some public data that we want to authenticate";
624
625 let encrypted = encrypt_with_aad(data, key, aad, CiphertextVersion::V2).unwrap();
626
627 let encrypted: Vec<u8> = encrypted.into();
628
629 let encrypted = Ciphertext::try_from(encrypted.as_slice()).unwrap();
630 let decrypted = encrypted.decrypt_with_aad(key, aad).unwrap();
631
632 assert_eq!(decrypted, data);
633
634 let decrypted = encrypted.decrypt_with_aad(key, wrong_aad);
635
636 assert!(decrypted.is_err());
637
638 let decrypted = encrypted.decrypt(key);
639
640 assert!(decrypted.is_err());
641}
642
643#[test]
644fn asymmetric_test() {
645 use super::key::{generate_keypair, KeyVersion};
646
647 let test_plaintext = b"this is a test data";
648
649 let keypair = generate_keypair(KeyVersion::Latest);
650
651 let encrypted_data = encrypt_asymmetric(
652 test_plaintext,
653 &keypair.public_key,
654 CiphertextVersion::Latest,
655 )
656 .unwrap();
657
658 let encrypted_data_vec: Vec<u8> = encrypted_data.into();
659
660 assert_ne!(encrypted_data_vec.len(), 0);
661
662 let encrypted_data = Ciphertext::try_from(encrypted_data_vec.as_slice()).unwrap();
663
664 let decrypted_data = encrypted_data
665 .decrypt_asymmetric(&keypair.private_key)
666 .unwrap();
667
668 assert_eq!(decrypted_data, test_plaintext);
669}
670
671#[test]
672fn asymmetric_aad_test() {
673 use super::key::{generate_keypair, KeyVersion};
674
675 let test_plaintext = b"this is a test data";
676 let aad = b"This is some public data that we want to authenticate";
677 let wrong_aad = b"this is some public data that we want to authenticate";
678
679 let keypair = generate_keypair(KeyVersion::Latest);
680
681 let encrypted_data = encrypt_asymmetric_with_aad(
682 test_plaintext,
683 &keypair.public_key,
684 aad,
685 CiphertextVersion::Latest,
686 )
687 .unwrap();
688
689 let encrypted_data_vec: Vec<u8> = encrypted_data.into();
690
691 assert_ne!(encrypted_data_vec.len(), 0);
692
693 let encrypted_data = Ciphertext::try_from(encrypted_data_vec.as_slice()).unwrap();
694
695 let decrypted_data = encrypted_data
696 .decrypt_asymmetric_with_aad(&keypair.private_key, aad)
697 .unwrap();
698
699 assert_eq!(decrypted_data, test_plaintext);
700
701 let decrypted = encrypted_data.decrypt_asymmetric_with_aad(&keypair.private_key, wrong_aad);
702
703 assert!(decrypted.is_err());
704
705 let decrypted = encrypted_data.decrypt_asymmetric(&keypair.private_key);
706
707 assert!(decrypted.is_err());
708}
709
710#[test]
711fn asymmetric_test_v2() {
712 use super::key::{generate_keypair, KeyVersion};
713
714 let test_plaintext = b"this is a test data";
715
716 let keypair = generate_keypair(KeyVersion::V1);
717
718 let encrypted_data =
719 encrypt_asymmetric(test_plaintext, &keypair.public_key, CiphertextVersion::V2).unwrap();
720
721 assert_eq!(encrypted_data.header.version, CiphertextVersion::V2);
722 let encrypted_data_vec: Vec<u8> = encrypted_data.into();
723
724 assert_ne!(encrypted_data_vec.len(), 0);
725
726 let encrypted_data = Ciphertext::try_from(encrypted_data_vec.as_slice()).unwrap();
727
728 let decrypted_data = encrypted_data
729 .decrypt_asymmetric(&keypair.private_key)
730 .unwrap();
731
732 assert_eq!(decrypted_data, test_plaintext);
733}
734
735#[test]
736fn asymmetric_aad_test_v2() {
737 use super::key::{generate_keypair, KeyVersion};
738
739 let test_plaintext = b"this is a test data";
740 let aad = b"This is some public data that we want to authenticate";
741 let wrong_aad = b"this is some public data that we want to authenticate";
742
743 let keypair = generate_keypair(KeyVersion::V1);
744
745 let encrypted_data = encrypt_asymmetric_with_aad(
746 test_plaintext,
747 &keypair.public_key,
748 aad,
749 CiphertextVersion::V2,
750 )
751 .unwrap();
752
753 let encrypted_data_vec: Vec<u8> = encrypted_data.into();
754
755 assert_ne!(encrypted_data_vec.len(), 0);
756
757 let encrypted_data = Ciphertext::try_from(encrypted_data_vec.as_slice()).unwrap();
758
759 let decrypted_data = encrypted_data
760 .decrypt_asymmetric_with_aad(&keypair.private_key, aad)
761 .unwrap();
762
763 assert_eq!(decrypted_data, test_plaintext);
764
765 let decrypted = encrypted_data.decrypt_asymmetric_with_aad(&keypair.private_key, wrong_aad);
766
767 assert!(decrypted.is_err());
768
769 let decrypted = encrypted_data.decrypt_asymmetric(&keypair.private_key);
770
771 assert!(decrypted.is_err());
772}
773
774#[test]
775fn encrypt_decrypt_with_secret_key() {
776 use super::key::{generate_secret_key, KeyVersion};
777
778 let data = b"somesecretdata";
779 let key = generate_secret_key(KeyVersion::Latest);
780
781 let encrypted = encrypt_with_secret_key(data, &key, CiphertextVersion::Latest).unwrap();
782 let decrypted = encrypted.decrypt_with_secret_key(&key).unwrap();
783
784 assert_eq!(decrypted, data);
785}
786
787#[test]
788fn encrypt_decrypt_with_secret_key_aad() {
789 use super::key::{generate_secret_key, KeyVersion};
790
791 let data = b"somesecretdata";
792 let aad = b"somepublicdata";
793 let wrong_aad = b"somewrongdata";
794 let key = generate_secret_key(KeyVersion::Latest);
795
796 let encrypted =
797 encrypt_with_secret_key_and_aad(data, &key, aad, CiphertextVersion::Latest).unwrap();
798 let decrypted = encrypted
799 .decrypt_with_secret_key_and_aad(&key, aad)
800 .unwrap();
801
802 assert_eq!(decrypted, data);
803
804 assert!(encrypted
805 .decrypt_with_secret_key_and_aad(&key, wrong_aad)
806 .is_err());
807 assert!(encrypted.decrypt_with_secret_key(&key).is_err());
808}
809
810#[test]
811fn encrypt_decrypt_with_secret_key_v1() {
812 use super::key::{generate_secret_key, KeyVersion};
813
814 let data = b"somesecretdata";
815 let key = generate_secret_key(KeyVersion::Latest);
816
817 let encrypted = encrypt_with_secret_key(data, &key, CiphertextVersion::V1).unwrap();
818
819 assert_eq!(encrypted.header.version, CiphertextVersion::V1);
820
821 let encrypted_bytes: Vec<u8> = encrypted.into();
822 let encrypted = Ciphertext::try_from(encrypted_bytes.as_slice()).unwrap();
823 let decrypted = encrypted.decrypt_with_secret_key(&key).unwrap();
824
825 assert_eq!(decrypted, data);
826}
827
828#[test]
829fn encrypt_decrypt_with_secret_key_v2() {
830 use super::key::{generate_secret_key, KeyVersion};
831
832 let data = b"somesecretdata";
833 let key = generate_secret_key(KeyVersion::Latest);
834
835 let encrypted = encrypt_with_secret_key(data, &key, CiphertextVersion::V2).unwrap();
836
837 assert_eq!(encrypted.header.version, CiphertextVersion::V2);
838
839 let encrypted_bytes: Vec<u8> = encrypted.into();
840 let encrypted = Ciphertext::try_from(encrypted_bytes.as_slice()).unwrap();
841 let decrypted = encrypted.decrypt_with_secret_key(&key).unwrap();
842
843 assert_eq!(decrypted, data);
844}