1#[cfg(feature = "serde")]
108use serde::{Deserialize, Serialize};
109use subtle::ConstantTimeEq;
110use zeroize::{Zeroize, Zeroizing};
111
112use crate::constants::{
113 CRYPTO_BOX_BEFORENMBYTES, CRYPTO_BOX_MACBYTES, CRYPTO_BOX_NONCEBYTES,
114 CRYPTO_BOX_PUBLICKEYBYTES, CRYPTO_BOX_SEALBYTES, CRYPTO_BOX_SECRETKEYBYTES,
115};
116use crate::error::*;
117pub use crate::types::*;
118
119pub type PublicKey = StackByteArray<CRYPTO_BOX_PUBLICKEYBYTES>;
121pub type SecretKey = StackByteArray<CRYPTO_BOX_SECRETKEYBYTES>;
123pub type Nonce = StackByteArray<CRYPTO_BOX_NONCEBYTES>;
125pub type Mac = StackByteArray<CRYPTO_BOX_MACBYTES>;
128pub type KeyPair = crate::keypair::KeyPair<PublicKey, SecretKey>;
131
132#[cfg(any(all(feature = "protected", any(unix, windows)), all(doc, not(doctest))))]
133#[cfg_attr(all(feature = "nightly", doc), doc(cfg(feature = "protected")))]
134pub mod protected {
135 use super::*;
178 pub use crate::protected::*;
179
180 pub type PublicKey = HeapByteArray<CRYPTO_BOX_PUBLICKEYBYTES>;
183 pub type SecretKey = HeapByteArray<CRYPTO_BOX_SECRETKEYBYTES>;
186 pub type Nonce = HeapByteArray<CRYPTO_BOX_NONCEBYTES>;
189 pub type Mac = HeapByteArray<CRYPTO_BOX_MACBYTES>;
192
193 pub type LockedKeyPair = crate::keypair::KeyPair<Locked<PublicKey>, Locked<SecretKey>>;
196 pub type LockedROKeyPair = crate::keypair::KeyPair<LockedRO<PublicKey>, LockedRO<SecretKey>>;
199 pub type LockedBox = DryocBox<Locked<PublicKey>, Locked<Mac>, LockedBytes>;
201}
202
203#[cfg_attr(
204 feature = "serde",
205 derive(Zeroize, Clone, Debug, Serialize, Deserialize)
206)]
207#[cfg_attr(not(feature = "serde"), derive(Zeroize, Clone, Debug))]
208pub struct DryocBox<
212 EphemeralPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
213 Mac: ByteArray<CRYPTO_BOX_MACBYTES> + Zeroize,
214 Data: Bytes + Zeroize,
215> {
216 ephemeral_pk: Option<EphemeralPublicKey>,
217 tag: Mac,
218 data: Data,
219}
220
221pub type VecBox = DryocBox<PublicKey, Mac, Vec<u8>>;
223
224#[cfg(feature = "wincode")]
225unsafe impl<C: wincode::config::Config> wincode::SchemaWrite<C> for VecBox {
229 type Src = Self;
230
231 fn size_of(src: &Self::Src) -> wincode::WriteResult<usize> {
232 Ok(
233 <Option<[u8; CRYPTO_BOX_PUBLICKEYBYTES]> as wincode::SchemaWrite<C>>::size_of(
234 &src.ephemeral_pk.as_ref().map(|epk| *epk.as_array()),
235 )? + <[u8; CRYPTO_BOX_MACBYTES] as wincode::SchemaWrite<C>>::size_of(
236 src.tag.as_array(),
237 )? + <Vec<u8> as wincode::SchemaWrite<C>>::size_of(&src.data)?,
238 )
239 }
240
241 fn write(mut writer: impl wincode::io::Writer, src: &Self::Src) -> wincode::WriteResult<()> {
242 <Option<[u8; CRYPTO_BOX_PUBLICKEYBYTES]> as wincode::SchemaWrite<C>>::write(
243 writer.by_ref(),
244 &src.ephemeral_pk.as_ref().map(|epk| *epk.as_array()),
245 )?;
246 <[u8; CRYPTO_BOX_MACBYTES] as wincode::SchemaWrite<C>>::write(
247 writer.by_ref(),
248 src.tag.as_array(),
249 )?;
250 <Vec<u8> as wincode::SchemaWrite<C>>::write(writer, &src.data)
251 }
252}
253
254#[cfg(feature = "wincode")]
255unsafe impl<'de, C: wincode::config::Config> wincode::SchemaRead<'de, C> for VecBox {
258 type Dst = Self;
259
260 fn read(
261 mut reader: impl wincode::io::Reader<'de>,
262 dst: &mut std::mem::MaybeUninit<Self::Dst>,
263 ) -> wincode::ReadResult<()> {
264 let ephemeral_pk = <Option<[u8; CRYPTO_BOX_PUBLICKEYBYTES]> as wincode::SchemaRead<
265 'de,
266 C,
267 >>::get(reader.by_ref())?
268 .map(Into::into);
269 let tag = <[u8; CRYPTO_BOX_MACBYTES] as wincode::SchemaRead<'de, C>>::get(reader.by_ref())?;
270 let data = <Vec<u8> as wincode::SchemaRead<'de, C>>::get(reader)?;
271 dst.write(Self {
272 ephemeral_pk,
273 tag: tag.into(),
274 data,
275 });
276 Ok(())
277 }
278}
279
280impl<
281 EphemeralPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
282 Mac: NewByteArray<CRYPTO_BOX_MACBYTES> + Zeroize,
283 Data: NewBytes + ResizableBytes + Zeroize,
284> DryocBox<EphemeralPublicKey, Mac, Data>
285{
286 pub fn encrypt<
295 Message: Bytes + ?Sized,
296 Nonce: ByteArray<CRYPTO_BOX_NONCEBYTES>,
297 RecipientPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES>,
298 SenderSecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES>,
299 >(
300 message: &Message,
301 nonce: &Nonce,
302 recipient_public_key: &RecipientPublicKey,
303 sender_secret_key: &SenderSecretKey,
304 ) -> Result<Self, Error> {
305 use crate::classic::crypto_box::crypto_box_detached;
306
307 let mut dryocbox = Self {
308 ephemeral_pk: None,
309 tag: Mac::new_byte_array(),
310 data: Data::new_bytes(),
311 };
312
313 dryocbox.data.resize(message.as_slice().len(), 0);
314
315 crypto_box_detached(
316 dryocbox.data.as_mut_slice(),
317 dryocbox.tag.as_mut_array(),
318 message.as_slice(),
319 nonce.as_array(),
320 recipient_public_key.as_array(),
321 sender_secret_key.as_array(),
322 )?;
323
324 Ok(dryocbox)
325 }
326
327 pub fn precalc_encrypt<
335 PrecalcSecretKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize,
336 Message: Bytes + ?Sized,
337 Nonce: ByteArray<CRYPTO_BOX_NONCEBYTES>,
338 >(
339 message: &Message,
340 nonce: &Nonce,
341 precalc_secret_key: &PrecalcSecretKey,
342 ) -> Result<Self, Error> {
343 use crate::classic::crypto_box::crypto_box_detached_afternm;
344
345 let mut dryocbox = Self {
346 ephemeral_pk: None,
347 tag: Mac::new_byte_array(),
348 data: Data::new_bytes(),
349 };
350
351 dryocbox.data.resize(message.as_slice().len(), 0);
352
353 crypto_box_detached_afternm(
354 dryocbox.data.as_mut_slice(),
355 dryocbox.tag.as_mut_array(),
356 message.as_slice(),
357 nonce.as_array(),
358 precalc_secret_key.as_array(),
359 )?;
360
361 Ok(dryocbox)
362 }
363}
364
365impl<
366 EphemeralPublicKey: NewByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
367 Mac: NewByteArray<CRYPTO_BOX_MACBYTES> + Zeroize,
368 Data: NewBytes + ResizableBytes + Zeroize,
369> DryocBox<EphemeralPublicKey, Mac, Data>
370{
371 pub fn seal<
386 Message: Bytes + ?Sized,
387 RecipientPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES>,
388 >(
389 message: &Message,
390 recipient_public_key: &RecipientPublicKey,
391 ) -> Result<Self, Error> {
392 use crate::classic::crypto_box::{
393 crypto_box_detached, crypto_box_keypair, crypto_box_seal_nonce,
394 };
395
396 let mut nonce = Nonce::new_byte_array();
397 let (epk, esk) = crypto_box_keypair();
398 let esk = Zeroizing::new(esk);
399 crypto_box_seal_nonce(nonce.as_mut_array(), &epk, recipient_public_key.as_array());
400
401 let mut pk = EphemeralPublicKey::new_byte_array();
402 pk.copy_from_slice(&epk);
403
404 let mut dryocbox = Self {
405 ephemeral_pk: Some(pk),
406 tag: Mac::new_byte_array(),
407 data: Data::new_bytes(),
408 };
409
410 dryocbox.data.resize(message.as_slice().len(), 0);
411
412 crypto_box_detached(
413 dryocbox.data.as_mut_slice(),
414 dryocbox.tag.as_mut_array(),
415 message.as_slice(),
416 nonce.as_array(),
417 recipient_public_key.as_array(),
418 &esk,
419 )?;
420
421 Ok(dryocbox)
422 }
423}
424
425impl<
426 'a,
427 EphemeralPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + std::convert::TryFrom<&'a [u8]> + Zeroize,
428 Mac: ByteArray<CRYPTO_BOX_MACBYTES> + std::convert::TryFrom<&'a [u8]> + Zeroize,
429 Data: Bytes + From<&'a [u8]> + Zeroize,
430> DryocBox<EphemeralPublicKey, Mac, Data>
431{
432 pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, Error> {
441 if bytes.len() < CRYPTO_BOX_MACBYTES {
442 Err(length_error!(crate::ErrorContext::Box, bytes.len(), min CRYPTO_BOX_MACBYTES))
443 } else {
444 let (tag, data) = bytes.split_at(CRYPTO_BOX_MACBYTES);
445 Ok(Self {
446 ephemeral_pk: None,
447 tag: Mac::try_from(tag)
448 .map_err(|_| Error::invalid_encoding(crate::ErrorContext::AuthenticationTag))?,
449 data: Data::from(data),
450 })
451 }
452 }
453
454 pub fn from_sealed_bytes(bytes: &'a [u8]) -> Result<Self, Error> {
465 if bytes.len() < CRYPTO_BOX_SEALBYTES {
466 Err(
467 length_error!(crate::ErrorContext::SealedBox, bytes.len(), min CRYPTO_BOX_SEALBYTES),
468 )
469 } else {
470 let (seal, data) = bytes.split_at(CRYPTO_BOX_SEALBYTES);
471 let (epk, tag) = seal.split_at(CRYPTO_BOX_PUBLICKEYBYTES);
472 Ok(Self {
473 ephemeral_pk: Some(
474 EphemeralPublicKey::try_from(epk)
475 .map_err(|_| Error::invalid_key(crate::ErrorContext::EphemeralPublicKey))?,
476 ),
477 tag: Mac::try_from(tag)
478 .map_err(|_| Error::invalid_encoding(crate::ErrorContext::AuthenticationTag))?,
479 data: Data::from(data),
480 })
481 }
482 }
483}
484
485impl<
486 EphemeralPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
487 Mac: ByteArray<CRYPTO_BOX_MACBYTES> + Zeroize,
488 Data: Bytes + Zeroize,
489> DryocBox<EphemeralPublicKey, Mac, Data>
490{
491 pub fn from_parts(tag: Mac, data: Data, ephemeral_pk: Option<EphemeralPublicKey>) -> Self {
494 Self {
495 ephemeral_pk,
496 tag,
497 data,
498 }
499 }
500
501 pub fn to_vec(&self) -> Vec<u8> {
503 self.to_bytes()
504 }
505
506 pub fn into_parts(self) -> (Mac, Data, Option<EphemeralPublicKey>) {
509 (self.tag, self.data, self.ephemeral_pk)
510 }
511
512 pub fn decrypt<
522 Nonce: ByteArray<CRYPTO_BOX_NONCEBYTES>,
523 SenderPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES>,
524 RecipientSecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES>,
525 Output: ResizableBytes + NewBytes,
526 >(
527 &self,
528 nonce: &Nonce,
529 sender_public_key: &SenderPublicKey,
530 recipient_secret_key: &RecipientSecretKey,
531 ) -> Result<Output, Error> {
532 use crate::classic::crypto_box::*;
533
534 let mut message = Output::new_bytes();
535 message.resize(self.data.as_slice().len(), 0);
536
537 crypto_box_open_detached(
538 message.as_mut_slice(),
539 self.tag.as_array(),
540 self.data.as_slice(),
541 nonce.as_array(),
542 sender_public_key.as_array(),
543 recipient_secret_key.as_array(),
544 )?;
545
546 Ok(message)
547 }
548
549 pub fn precalc_decrypt<
558 PrecalcSecretKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize,
559 Nonce: ByteArray<CRYPTO_BOX_NONCEBYTES>,
560 Output: ResizableBytes + NewBytes,
561 >(
562 &self,
563 nonce: &Nonce,
564 precalc_secret_key: &PrecalcSecretKey,
565 ) -> Result<Output, Error> {
566 use crate::classic::crypto_box::crypto_box_open_detached_afternm;
567
568 let mut message = Output::new_bytes();
569 message.resize(self.data.as_slice().len(), 0);
570
571 crypto_box_open_detached_afternm(
572 message.as_mut_slice(),
573 self.tag.as_array(),
574 self.data.as_slice(),
575 nonce.as_array(),
576 precalc_secret_key.as_array(),
577 )?;
578
579 Ok(message)
580 }
581
582 pub fn unseal<
592 RecipientPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
593 RecipientSecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES> + Zeroize,
594 Output: ResizableBytes + NewBytes + Zeroize,
595 >(
596 &self,
597 recipient_keypair: &crate::keypair::KeyPair<RecipientPublicKey, RecipientSecretKey>,
598 ) -> Result<Output, Error> {
599 use crate::classic::crypto_box::*;
600
601 match &self.ephemeral_pk {
602 Some(epk) => {
603 let mut nonce = Nonce::new_byte_array();
604 crypto_box_seal_nonce(
605 nonce.as_mut_array(),
606 epk.as_array(),
607 recipient_keypair.public_key.as_array(),
608 );
609
610 let mut message = Output::new_bytes();
611 message.resize(self.data.as_slice().len(), 0);
612
613 crypto_box_open_detached(
614 message.as_mut_slice(),
615 self.tag.as_array(),
616 self.data.as_slice(),
617 nonce.as_array(),
618 epk.as_array(),
619 recipient_keypair.secret_key.as_array(),
620 )?;
621
622 Ok(message)
623 }
624 None => Err(Error::missing_data(crate::ErrorContext::EphemeralPublicKey)),
625 }
626 }
627
628 pub fn to_bytes<Bytes: NewBytes + ResizableBytes>(&self) -> Bytes {
630 let mut data = Bytes::new_bytes();
631 match &self.ephemeral_pk {
632 Some(epk) => {
633 data.resize(epk.len() + self.tag.len() + self.data.len(), 0);
634 let s = data.as_mut_slice();
635 s[..CRYPTO_BOX_PUBLICKEYBYTES].copy_from_slice(epk.as_slice());
636 s[CRYPTO_BOX_PUBLICKEYBYTES..CRYPTO_BOX_SEALBYTES]
637 .copy_from_slice(self.tag.as_slice());
638 s[CRYPTO_BOX_SEALBYTES..].copy_from_slice(self.data.as_slice());
639 }
640 None => {
641 data.resize(self.tag.len() + self.data.len(), 0);
642 let s = data.as_mut_slice();
643 s[..CRYPTO_BOX_MACBYTES].copy_from_slice(self.tag.as_slice());
644 s[CRYPTO_BOX_MACBYTES..].copy_from_slice(self.data.as_slice());
645 }
646 }
647 data
648 }
649}
650
651impl DryocBox<PublicKey, Mac, Vec<u8>> {
652 pub fn encrypt_to_vecbox<
660 Message: Bytes + ?Sized,
661 SecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES>,
662 >(
663 message: &Message,
664 nonce: &Nonce,
665 recipient_public_key: &PublicKey,
666 sender_secret_key: &SecretKey,
667 ) -> Result<Self, Error> {
668 Self::encrypt(message, nonce, recipient_public_key, sender_secret_key)
669 }
670
671 pub fn precalc_encrypt_to_vecbox<
679 Message: Bytes + ?Sized,
680 PrecalcSecretKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize,
681 >(
682 message: &Message,
683 nonce: &Nonce,
684 precalc_secret_key: &PrecalcSecretKey,
685 ) -> Result<Self, Error> {
686 Self::precalc_encrypt(message, nonce, precalc_secret_key)
687 }
688
689 pub fn seal_to_vecbox<Message: Bytes + ?Sized>(
703 message: &Message,
704 recipient_public_key: &PublicKey,
705 ) -> Result<Self, Error> {
706 Self::seal(message, recipient_public_key)
707 }
708
709 pub fn decrypt_to_vec<SecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES>>(
718 &self,
719 nonce: &Nonce,
720 sender_public_key: &PublicKey,
721 recipient_secret_key: &SecretKey,
722 ) -> Result<Vec<u8>, Error> {
723 self.decrypt(nonce, sender_public_key, recipient_secret_key)
724 }
725
726 pub fn precalc_decrypt_to_vec<
735 PrecalcSecretKey: ByteArray<CRYPTO_BOX_BEFORENMBYTES> + Zeroize,
736 >(
737 &self,
738 nonce: &Nonce,
739 precalc_secret_key: &PrecalcSecretKey,
740 ) -> Result<Vec<u8>, Error> {
741 self.precalc_decrypt(nonce, precalc_secret_key)
742 }
743
744 pub fn unseal_to_vec<
753 RecipientPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
754 RecipientSecretKey: ByteArray<CRYPTO_BOX_SECRETKEYBYTES> + Zeroize,
755 >(
756 &self,
757 recipient_keypair: &crate::keypair::KeyPair<RecipientPublicKey, RecipientSecretKey>,
758 ) -> Result<Vec<u8>, Error> {
759 self.unseal(recipient_keypair)
760 }
761}
762
763impl<
764 'a,
765 EphemeralPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
766 Mac: ByteArray<CRYPTO_BOX_MACBYTES> + Zeroize,
767 Data: Bytes + ResizableBytes + From<&'a [u8]> + Zeroize,
768> DryocBox<EphemeralPublicKey, Mac, Data>
769{
770 pub fn new_with_data_and_mac(tag: Mac, input: &'a [u8]) -> Self {
773 Self {
774 ephemeral_pk: None,
775 tag,
776 data: input.into(),
777 }
778 }
779
780 pub fn new_with_epk_data_and_mac(
783 ephemeral_pk: EphemeralPublicKey,
784 tag: Mac,
785 input: &'a [u8],
786 ) -> Self {
787 Self {
788 ephemeral_pk: Some(ephemeral_pk),
789 tag,
790 data: input.into(),
791 }
792 }
793}
794
795impl<
796 EphemeralPublicKey: ByteArray<CRYPTO_BOX_PUBLICKEYBYTES> + Zeroize,
797 Mac: ByteArray<CRYPTO_BOX_MACBYTES> + Zeroize,
798 Data: Bytes + Zeroize,
799> PartialEq<DryocBox<EphemeralPublicKey, Mac, Data>> for DryocBox<EphemeralPublicKey, Mac, Data>
800{
801 fn eq(&self, other: &Self) -> bool {
802 if let Some(our_epk) = &self.ephemeral_pk {
803 if let Some(their_epk) = &other.ephemeral_pk {
804 self.tag.as_slice().ct_eq(other.tag.as_slice()).unwrap_u8() == 1
805 && self
806 .data
807 .as_slice()
808 .ct_eq(other.data.as_slice())
809 .unwrap_u8()
810 == 1
811 && our_epk.as_slice().ct_eq(their_epk.as_slice()).unwrap_u8() == 1
812 } else {
813 false
814 }
815 } else if other.ephemeral_pk.is_none() {
816 self.tag.as_slice().ct_eq(other.tag.as_slice()).unwrap_u8() == 1
817 && self
818 .data
819 .as_slice()
820 .ct_eq(other.data.as_slice())
821 .unwrap_u8()
822 == 1
823 } else {
824 false
825 }
826 }
827}
828
829#[cfg(test)]
830mod tests {
831 use super::*;
832 use crate::precalc::PrecalcSecretKey;
833
834 #[test]
835 fn unseal_requires_an_ephemeral_public_key() {
836 let box_without_ephemeral_key =
837 VecBox::from_bytes(&[0u8; CRYPTO_BOX_MACBYTES]).expect("a regular box should parse");
838 let recipient_keypair = KeyPair::generate();
839
840 let error = box_without_ephemeral_key
841 .unseal::<_, _, Vec<u8>>(&recipient_keypair)
842 .expect_err("a regular box cannot be unsealed");
843 assert!(matches!(
844 error,
845 Error::MissingData {
846 context: crate::ErrorContext::EphemeralPublicKey,
847 }
848 ));
849 }
850
851 #[test]
852 fn test_decrypt_failure_empty() {
853 for _ in 0..20 {
854 use crate::keypair::*;
855
856 let invalid_key = KeyPair::generate();
857 let invalid_key_copy_1 = invalid_key.clone();
858 let invalid_key_copy_2 = invalid_key.clone();
859 let nonce = Nonce::generate();
860
861 let dryocbox: VecBox =
862 DryocBox::from_bytes(b"trollolllololololollollolololololol").expect("ok");
863 DryocBox::decrypt::<
864 Nonce,
865 crate::classic::crypto_box::PublicKey,
866 crate::classic::crypto_box::SecretKey,
867 Vec<u8>,
868 >(
869 &dryocbox,
870 &nonce,
871 &invalid_key_copy_1.public_key,
872 &invalid_key_copy_2.secret_key,
873 )
874 .expect_err("hmm");
875 }
876 }
877
878 #[test]
879 fn test_copy() {
880 for _ in 0..20 {
881 use std::convert::TryFrom;
882
883 use crate::rng::*;
884
885 let mut data1: Vec<u8> = vec![0u8; 1024];
886 copy_randombytes(data1.as_mut_slice());
887 let data1_copy = data1.clone();
888
889 let dryocbox: VecBox = DryocBox::from_bytes(&data1).expect("ok");
890 assert_eq!(dryocbox.data.as_slice(), &data1_copy[CRYPTO_BOX_MACBYTES..]);
891 assert_eq!(dryocbox.tag.as_slice(), &data1_copy[..CRYPTO_BOX_MACBYTES]);
892
893 let data1 = data1_copy.clone();
894 let (tag, data) = data1.split_at(CRYPTO_BOX_MACBYTES);
895 let dryocbox: VecBox =
896 DryocBox::new_with_data_and_mac(Mac::try_from(tag).expect("mac"), data);
897 assert_eq!(dryocbox.data.as_slice(), &data1_copy[CRYPTO_BOX_MACBYTES..]);
898 assert_eq!(dryocbox.tag.as_array(), &data1_copy[..CRYPTO_BOX_MACBYTES]);
899 }
900 }
901
902 #[test]
903 fn test_precalc_encrypt_decrypt() {
904 let keypair_sender = KeyPair::generate();
905 let keypair_recipient = KeyPair::generate();
906 let nonce = Nonce::generate();
907
908 let message = b"To be, or not to be, that is the question:";
909 let precalc_secret_key = PrecalcSecretKey::precalculate(
910 &keypair_recipient.public_key,
911 &keypair_sender.secret_key,
912 )
913 .expect("precalculation failed");
914
915 let dryocbox: VecBox = DryocBox::precalc_encrypt(message, &nonce, &precalc_secret_key)
916 .expect("unable to encrypt");
917
918 let decrypted: Vec<u8> = dryocbox
919 .precalc_decrypt(&nonce, &precalc_secret_key)
920 .expect("unable to decrypt");
921
922 assert_eq!(message, decrypted.as_slice());
923 }
924
925 #[test]
926 fn test_precalc_encrypt_to_vecbox_decrypt_to_vecbox() {
927 let keypair_sender = KeyPair::generate();
928 let keypair_recipient = KeyPair::generate();
929 let nonce = Nonce::generate();
930
931 let message = b"All the world's a stage, and all the men and women merely players:";
932 let precalc_secret_key = PrecalcSecretKey::precalculate(
933 &keypair_recipient.public_key,
934 &keypair_sender.secret_key,
935 )
936 .expect("precalculation failed");
937
938 let dryocbox = DryocBox::precalc_encrypt_to_vecbox(message, &nonce, &precalc_secret_key)
939 .expect("unable to encrypt");
940
941 let decrypted = dryocbox
942 .precalc_decrypt_to_vec(&nonce, &precalc_secret_key)
943 .expect("unable to decrypt");
944
945 assert_eq!(message, decrypted.as_slice());
946 }
947
948 #[test]
949 fn test_precalc_encrypt_decrypt_with_different_messages() {
950 let keypair_sender = KeyPair::generate();
951 let keypair_recipient = KeyPair::generate();
952 let nonce = Nonce::generate();
953
954 let messages: Vec<&[u8]> = vec![
955 b"Now is the winter of our discontent, made glorious summer by this sun of York;",
956 b"Friends, Romans, countrymen, lend me your ears; I come to bury Caesar, not to praise him.",
957 b"A horse! a horse! my kingdom for a horse!",
958 b"Good night, good night! parting is such sweet sorrow, that I shall say good night till it be morrow.",
959 ];
960
961 let precalc_secret_key = PrecalcSecretKey::precalculate(
962 &keypair_recipient.public_key,
963 &keypair_sender.secret_key,
964 )
965 .expect("precalculation failed");
966
967 for message in &messages {
968 let dryocbox: VecBox = DryocBox::precalc_encrypt(message, &nonce, &precalc_secret_key)
969 .expect("unable to encrypt");
970
971 let decrypted: Vec<u8> = dryocbox
972 .precalc_decrypt(&nonce, &precalc_secret_key)
973 .expect("unable to decrypt");
974
975 assert_eq!(*message, decrypted.as_slice());
976 }
977 }
978
979 #[test]
980 fn test_precalc_encrypt_to_vecbox_decrypt_to_vecbox_with_different_messages() {
981 let keypair_sender = KeyPair::generate();
982 let keypair_recipient = KeyPair::generate();
983 let nonce = Nonce::generate();
984
985 let messages: Vec<&[u8]> = vec![
986 b"Out, out brief candle! Life's but a walking shadow, a poor player that struts and frets his hour upon the stage and then is heard no more.",
987 b"Some are born great, some achieve greatness, and some have greatness thrust upon them.",
988 b"The lady doth protest too much, methinks.",
989 b"What's in a name? That which we call a rose by any other name would smell as sweet.",
990 ];
991
992 let precalc_secret_key = PrecalcSecretKey::precalculate(
993 &keypair_recipient.public_key,
994 &keypair_sender.secret_key,
995 )
996 .expect("precalculation failed");
997
998 for message in &messages {
999 let dryocbox =
1000 DryocBox::precalc_encrypt_to_vecbox(message, &nonce, &precalc_secret_key)
1001 .expect("unable to encrypt");
1002
1003 let decrypted = dryocbox
1004 .precalc_decrypt_to_vec(&nonce, &precalc_secret_key)
1005 .expect("unable to decrypt");
1006
1007 assert_eq!(*message, decrypted.as_slice());
1008 }
1009 }
1010
1011 #[cfg(dryoc_native_tests)]
1012 mod native_tests {
1013 use super::*;
1014
1015 #[test]
1016 fn test_dryocbox_vecbox() {
1017 for i in 0..20 {
1018 use base64::Engine as _;
1019 use base64::engine::general_purpose;
1020 use sodiumoxide::crypto::box_;
1021 use sodiumoxide::crypto::box_::{Nonce as SONonce, PublicKey, SecretKey};
1022
1023 let keypair_sender = KeyPair::generate();
1024 let keypair_recipient = KeyPair::generate();
1025 let keypair_sender_copy = keypair_sender.clone();
1026 let keypair_recipient_copy = keypair_recipient.clone();
1027 let nonce = Nonce::generate();
1028 let words = vec!["hello1".to_string(); i];
1029 let message = words.join(" :D ");
1030 let message_copy = message.clone();
1031 let dryocbox = DryocBox::encrypt_to_vecbox(
1032 message.as_bytes(),
1033 &nonce,
1034 &keypair_recipient.public_key,
1035 &keypair_sender.secret_key,
1036 )
1037 .unwrap();
1038
1039 let ciphertext = dryocbox.to_vec();
1040
1041 let so_ciphertext = box_::seal(
1042 message_copy.as_bytes(),
1043 &SONonce::from_slice(&nonce).unwrap(),
1044 &PublicKey::from_slice(&keypair_recipient_copy.public_key).unwrap(),
1045 &SecretKey::from_slice(&keypair_sender_copy.secret_key).unwrap(),
1046 );
1047
1048 assert_eq!(
1049 general_purpose::STANDARD.encode(&ciphertext),
1050 general_purpose::STANDARD.encode(&so_ciphertext)
1051 );
1052
1053 let keypair_sender = keypair_sender_copy.clone();
1054 let keypair_recipient = keypair_recipient_copy.clone();
1055
1056 let m = dryocbox
1057 .decrypt_to_vec(
1058 &nonce,
1059 &keypair_sender.public_key,
1060 &keypair_recipient.secret_key,
1061 )
1062 .expect("hmm");
1063 let so_m = box_::open(
1064 &ciphertext,
1065 &SONonce::from_slice(&nonce).unwrap(),
1066 &PublicKey::from_slice(&keypair_recipient_copy.public_key).unwrap(),
1067 &SecretKey::from_slice(&keypair_sender_copy.secret_key).unwrap(),
1068 )
1069 .expect("HMMM");
1070
1071 assert_eq!(m, message_copy.as_bytes());
1072 assert_eq!(m, so_m);
1073 }
1074 }
1075
1076 #[test]
1077 fn test_decrypt_failure() {
1078 for i in 0..20 {
1079 use base64::Engine as _;
1080 use base64::engine::general_purpose;
1081 use sodiumoxide::crypto::box_;
1082 use sodiumoxide::crypto::box_::{
1083 Nonce as SONonce, PublicKey as SOPublicKey, SecretKey as SOSecretKey,
1084 };
1085
1086 let keypair_sender = KeyPair::generate();
1087 let keypair_recipient = KeyPair::generate();
1088 let keypair_sender_copy = keypair_sender.clone();
1089 let keypair_recipient_copy = keypair_recipient.clone();
1090 let nonce = Nonce::generate();
1091 let words = vec!["hello1".to_string(); i];
1092 let message = words.join(" :D ");
1093 let message_copy = message.clone();
1094 let dryocbox = DryocBox::encrypt_to_vecbox(
1095 message.as_bytes(),
1096 &nonce,
1097 &keypair_recipient.public_key,
1098 &keypair_sender.secret_key,
1099 )
1100 .unwrap();
1101
1102 let ciphertext = dryocbox.to_vec();
1103
1104 let so_ciphertext = box_::seal(
1105 message_copy.as_bytes(),
1106 &SONonce::from_slice(&nonce).unwrap(),
1107 &SOPublicKey::from_slice(&keypair_recipient_copy.public_key).unwrap(),
1108 &SOSecretKey::from_slice(&keypair_sender_copy.secret_key).unwrap(),
1109 );
1110
1111 assert_eq!(
1112 general_purpose::STANDARD.encode(&ciphertext),
1113 general_purpose::STANDARD.encode(&so_ciphertext)
1114 );
1115
1116 let invalid_key = KeyPair::generate();
1117 let invalid_key_copy_1 = invalid_key.clone();
1118 let invalid_key_copy_2 = invalid_key.clone();
1119
1120 DryocBox::decrypt::<Nonce, PublicKey, SecretKey, Vec<u8>>(
1121 &dryocbox,
1122 &nonce,
1123 &invalid_key_copy_1.public_key,
1124 &invalid_key_copy_2.secret_key,
1125 )
1126 .expect_err("hmm");
1127 box_::open(
1128 &ciphertext,
1129 &SONonce::from_slice(&nonce).unwrap(),
1130 &SOPublicKey::from_slice(&invalid_key.public_key).unwrap(),
1131 &SOSecretKey::from_slice(&invalid_key.secret_key).unwrap(),
1132 )
1133 .expect_err("HMMM");
1134 }
1135 }
1136
1137 #[test]
1138 fn test_dryocbox_seal_vecbox() {
1139 for i in 0..20 {
1140 use sodiumoxide::crypto::box_::{
1141 PublicKey as SOPublicKey, SecretKey as SOSecretKey,
1142 };
1143 use sodiumoxide::crypto::sealedbox::curve25519blake2bxsalsa20poly1305;
1144
1145 let keypair_recipient = KeyPair::generate();
1146 let words = vec!["hello1".to_string(); i];
1147 let message = words.join(" :D ");
1148 let message_copy = message.clone();
1149 let dryocbox =
1150 DryocBox::seal_to_vecbox(message.as_bytes(), &keypair_recipient.public_key)
1151 .unwrap();
1152
1153 let ciphertext = dryocbox.to_vec();
1154
1155 let m = dryocbox.unseal_to_vec(&keypair_recipient).expect("hmm");
1156 let so_m = curve25519blake2bxsalsa20poly1305::open(
1157 ciphertext.as_slice(),
1158 &SOPublicKey::from_slice(keypair_recipient.public_key.as_slice()).unwrap(),
1159 &SOSecretKey::from_slice(keypair_recipient.secret_key.as_slice()).unwrap(),
1160 )
1161 .unwrap();
1162
1163 assert_eq!(m, message_copy.as_bytes());
1164 assert_eq!(m, so_m);
1165 }
1166 }
1167
1168 #[test]
1169 fn test_dryocbox_unseal_vecbox() {
1170 for i in 0..20 {
1171 use sodiumoxide::crypto::box_::PublicKey as SOPublicKey;
1172 use sodiumoxide::crypto::sealedbox::curve25519blake2bxsalsa20poly1305;
1173
1174 let keypair_recipient = KeyPair::generate();
1175 let words = vec!["hello1".to_string(); i];
1176 let message = words.join(" :D ");
1177
1178 let ciphertext = curve25519blake2bxsalsa20poly1305::seal(
1179 message.as_bytes(),
1180 &SOPublicKey::from_slice(keypair_recipient.public_key.as_slice()).unwrap(),
1181 );
1182
1183 let dryocbox =
1184 DryocBox::from_sealed_bytes(&ciphertext).expect("from sealed bytes failed");
1185
1186 let m = dryocbox.unseal_to_vec(&keypair_recipient).expect("hmm");
1187
1188 assert_eq!(m, message.as_bytes());
1189 }
1190 }
1191 }
1192}