1use crate::{
55 identity::{BareIdKey, IdentityKey},
56 lock::{lock_id_encrypt, BareLockKey, LockId, LockKey},
57 lockbox::*,
58 CryptoError, CryptoSrc,
59};
60
61use rand_core::{CryptoRng, RngCore};
62
63use zeroize::Zeroize;
64
65use std::{convert::TryFrom, fmt, sync::Arc};
66
67use blake2::{
68 Blake2bMac,
69 digest::{consts::U32, Mac, FixedOutput},
70};
71type V1KeyId = Blake2bMac<U32>;
72
73pub const DEFAULT_STREAM_VERSION: u8 = 1;
75
76pub const MIN_STREAM_VERSION: u8 = 1;
78
79pub const MAX_STREAM_VERSION: u8 = 1;
81
82const V1_STREAM_ID_SIZE: usize = 32;
83const V1_STREAM_KEY_SIZE: usize = 32;
84
85pub(crate) fn stream_id_size(_version: u8) -> usize {
88 1 + V1_STREAM_ID_SIZE
89}
90
91#[derive(Clone)]
121pub struct StreamKey {
122 interface: Arc<dyn StreamInterface>,
123}
124
125#[cfg(feature = "getrandom")]
126impl Default for StreamKey {
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132impl StreamKey {
133
134 pub fn from_interface(interface: Arc<dyn StreamInterface>) -> Self {
137 StreamKey { interface }
138 }
139
140 #[cfg(feature = "getrandom")]
142 pub fn new() -> StreamKey {
143 let interface = Arc::new(BareStreamKey::new());
144 Self::from_interface(interface)
145 }
146
147 pub fn with_rng<R>(csprng: &mut R) -> StreamKey
150 where
151 R: CryptoRng + RngCore,
152 {
153 let interface = Arc::new(BareStreamKey::with_rng(csprng));
154 Self::from_interface(interface)
155 }
156
157 pub fn with_rng_and_version<R>(csprng: &mut R, version: u8) -> Result<StreamKey, CryptoError>
160 where
161 R: CryptoRng + RngCore,
162 {
163 let interface = Arc::new(BareStreamKey::with_rng_and_version(csprng, version)?);
164 Ok(Self::from_interface(interface))
165 }
166
167 pub fn version(&self) -> u8 {
169 self.interface.id().version()
170 }
171
172 pub fn id(&self) -> &StreamId {
174 self.interface.id()
175 }
176
177 #[cfg(feature = "getrandom")]
178 pub fn encrypt_data(
180 &self,
181 content: &[u8],
182 ) -> DataLockbox {
183 self.encrypt_data_with_rng(&mut rand_core::OsRng, content)
184 }
185
186 pub fn encrypt_data_with_rng<R: CryptoRng + RngCore>(
189 &self,
190 csprng: &mut R,
191 content: &[u8],
192 ) -> DataLockbox {
193 data_lockbox_from_parts(
194 self.interface
195 .encrypt(csprng, LockboxType::Data(true), content),
196 )
197 }
198
199 pub fn decrypt_lock_key(&self, lockbox: &LockLockboxRef) -> Result<LockKey, CryptoError> {
202 self.interface.decrypt_lock_key(lockbox)
203 }
204
205 pub fn decrypt_identity_key(
208 &self,
209 lockbox: &IdentityLockboxRef,
210 ) -> Result<IdentityKey, CryptoError> {
211 self.interface.decrypt_identity_key(lockbox)
212 }
213
214 pub fn decrypt_stream_key(&self, lockbox: &StreamLockboxRef) -> Result<StreamKey, CryptoError> {
217 self.interface.decrypt_stream_key(lockbox)
218 }
219
220 pub fn decrypt_data(&self, lockbox: &DataLockboxRef) -> Result<Vec<u8>, CryptoError> {
222 self.interface.decrypt_data(lockbox)
223 }
224
225 pub fn export_for_lock(
228 &self,
229 lock: &LockId,
230 ) -> Option<StreamLockbox> {
231 self.interface.self_export_lock(&mut rand_core::OsRng, lock)
232 }
233
234 pub fn export_for_lock_with_rng<R: CryptoRng + RngCore>(
237 &self,
238 csprng: &mut R,
239 lock: &LockId,
240 ) -> Option<StreamLockbox> {
241 self.interface.self_export_lock(csprng, lock)
242 }
243
244 #[cfg(feature = "getrandom")]
245 pub fn export_for_stream(
250 &self,
251 stream: &StreamKey,
252 ) -> Option<StreamLockbox> {
253 self.interface.self_export_stream(&mut rand_core::OsRng, stream)
254 }
255
256 pub fn export_for_stream_with_rng<R: CryptoRng + RngCore>(
261 &self,
262 csprng: &mut R,
263 stream: &StreamKey,
264 ) -> Option<StreamLockbox> {
265 self.interface.self_export_stream(csprng, stream)
266 }
267}
268
269pub fn stream_key_encrypt(
273 key: &StreamKey,
274 csprng: &mut dyn CryptoSrc,
275 lock_type: LockboxType,
276 content: &[u8],
277) -> Vec<u8> {
278 key.interface.encrypt(csprng, lock_type, content)
279}
280
281impl fmt::Debug for StreamKey {
282 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
283 f.debug_struct("StreamKey")
284 .field("version", &self.version())
285 .field("stream_id", &self.id().raw_identifier())
286 .finish()
287 }
288}
289
290impl fmt::Display for StreamKey {
291 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293 fmt::Display::fmt(self.id(), f)
294 }
295}
296
297impl<T: StreamInterface + 'static> From<T> for StreamKey {
298 fn from(value: T) -> Self {
299 Self::from_interface(Arc::new(value))
300 }
301}
302
303pub trait StreamInterface: Sync + Send {
308 fn id(&self) -> &StreamId;
310
311 fn encrypt(
314 &self,
315 csprng: &mut dyn CryptoSrc,
316 lock_type: LockboxType,
317 content: &[u8],
318 ) -> Vec<u8>;
319
320 fn decrypt_lock_key(&self, lockbox: &LockLockboxRef) -> Result<LockKey, CryptoError>;
322
323 fn decrypt_identity_key(
326 &self,
327 lockbox: &IdentityLockboxRef,
328 ) -> Result<IdentityKey, CryptoError>;
329
330 fn decrypt_stream_key(&self, lockbox: &StreamLockboxRef) -> Result<StreamKey, CryptoError>;
333
334 fn decrypt_data(&self, lockbox: &DataLockboxRef) -> Result<Vec<u8>, CryptoError>;
336
337 fn self_export_lock(
340 &self,
341 csprng: &mut dyn CryptoSrc,
342 receive_lock: &LockId,
343 ) -> Option<StreamLockbox>;
344
345 fn self_export_stream(
352 &self,
353 csprng: &mut dyn CryptoSrc,
354 receive_stream: &StreamKey,
355 ) -> Option<StreamLockbox>;
356}
357
358pub fn stream_id_from_key(version: u8, key: &[u8]) -> StreamId {
360 assert_eq!(version, 1u8, "StreamKey must have version of 1");
361 let mut hasher = V1KeyId::new_with_salt_and_personal(&[], &[], b"fog-crypto-sid").unwrap();
362 hasher.update(key);
363 let mut id = StreamId {
364 inner: Vec::with_capacity(1 + V1_STREAM_ID_SIZE),
365 };
366 id.inner.push(1u8);
367 let hash_raw = hasher.finalize_fixed();
368 id.inner.extend_from_slice(&hash_raw[..]);
369 id
370}
371
372pub struct BareStreamKey {
375 key: [u8; V1_STREAM_KEY_SIZE],
376 id: StreamId,
377}
378
379#[cfg(feature = "getrandom")]
380impl Default for BareStreamKey {
381 fn default() -> Self {
382 Self::new()
383 }
384}
385
386impl BareStreamKey {
387
388 #[cfg(feature = "getrandom")]
390 pub fn new() -> Self {
391 let mut key = [0; V1_STREAM_KEY_SIZE];
392 rand_core::OsRng.fill_bytes(&mut key);
393 let new = Self {
394 key,
395 id: stream_id_from_key(DEFAULT_STREAM_VERSION, &key),
396 };
397 key.zeroize();
398 debug_assert!(key.iter().all(|&x| x == 0));
399 debug_assert!(new.key.iter().any(|&x| x != 0));
400 new
401 }
402
403 pub fn with_rng<R>(csprng: &mut R) -> Self
405 where
406 R: CryptoRng + RngCore,
407 {
408 Self::with_rng_and_version(csprng, DEFAULT_STREAM_VERSION).unwrap()
409 }
410
411 pub fn with_rng_and_version<R>(csprng: &mut R, version: u8) -> Result<Self, CryptoError>
414 where
415 R: CryptoRng + RngCore,
416 {
417 if (version < MIN_STREAM_VERSION) || (version > MAX_STREAM_VERSION) {
418 return Err(CryptoError::UnsupportedVersion(version));
419 }
420
421 let mut key = [0; V1_STREAM_KEY_SIZE];
422 csprng.fill_bytes(&mut key);
423
424 let new = Self {
425 key,
426 id: stream_id_from_key(version, &key),
427 };
428 key.zeroize();
430 debug_assert!(key.iter().all(|&x| x == 0));
432 debug_assert!(new.key.iter().any(|&x| x != 0));
433
434 Ok(new)
435 }
436
437 pub fn encode_vec(&self, buf: &mut Vec<u8>) {
440 buf.reserve(1 + V1_STREAM_KEY_SIZE);
441 buf.push(1u8);
442 buf.extend_from_slice(&self.key);
443 }
444
445 fn decrypt_parts(
448 &self,
449 recipient: &LockboxRecipient,
450 parts: LockboxParts,
451 ) -> Result<Vec<u8>, CryptoError> {
452 if let LockboxRecipient::StreamId(id) = recipient {
455 if id != &self.id {
456 return Err(CryptoError::ObjectMismatch(
457 "StreamKey being used on a lockbox meant for a different StreamId",
458 ));
459 }
460 } else {
461 return Err(CryptoError::ObjectMismatch(
462 "Attempted to use a StreamKey to decrypt a lockbox with a LockId recipient",
463 ));
464 }
465 use chacha20poly1305::aead::Aead;
467 use chacha20poly1305::*;
468 let aead = XChaCha20Poly1305::new(Key::from_slice(&self.key));
469 let nonce = XNonce::from_slice(parts.nonce);
470 let payload = aead::Payload {
471 msg: parts.ciphertext,
472 aad: parts.additional,
473 };
474 aead.decrypt(nonce, payload)
475 .map_err(|_| CryptoError::DecryptFailed)
476 }
477}
478
479impl TryFrom<&[u8]> for BareStreamKey {
480 type Error = CryptoError;
481
482 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
483 let (version, key) = value.split_first().ok_or(CryptoError::BadLength {
484 step: "get StreamKey version",
485 expected: 1,
486 actual: 0,
487 })?;
488 let version = *version;
489 if version < MIN_STREAM_VERSION {
490 return Err(CryptoError::OldVersion(version));
491 }
492 if version > MAX_STREAM_VERSION {
493 return Err(CryptoError::UnsupportedVersion(version));
494 }
495
496 if key.len() != V1_STREAM_KEY_SIZE {
497 return Err(CryptoError::BadLength {
498 step: "get StreamKey key bytes",
499 expected: V1_STREAM_KEY_SIZE,
500 actual: key.len(),
501 });
502 }
503
504 let mut new = Self {
505 key: [0; V1_STREAM_KEY_SIZE],
506 id: stream_id_from_key(version, key),
507 };
508
509 new.key.copy_from_slice(&key[..32]);
510 Ok(new)
511 }
512}
513
514impl Drop for BareStreamKey {
515 fn drop(&mut self) {
516 self.key.zeroize();
517 }
518}
519
520impl StreamInterface for BareStreamKey {
521 fn id(&self) -> &StreamId {
522 &self.id
523 }
524
525 fn encrypt(
526 &self,
527 csprng: &mut dyn CryptoSrc,
528 lock_type: LockboxType,
529 content: &[u8],
530 ) -> Vec<u8> {
531 assert!(
532 lock_type.is_for_stream(),
533 "Tried to encrypt a non-stream-recipient lockbox with a StreamId"
534 );
535 use chacha20poly1305::aead::AeadInPlace;
536 use chacha20poly1305::{KeyInit, XChaCha20Poly1305, XNonce};
537
538 let id = self.id();
540 let version = id.version();
541 let tag_len = lockbox_tag_size(version);
542 let nonce_len = lockbox_nonce_size(version);
543 let header_len = 2 + id.size();
544 let len = header_len + nonce_len + content.len() + tag_len;
545 let mut lockbox: Vec<u8> = Vec::with_capacity(len);
546 let mut nonce = [0u8; crate::lockbox::V1_LOCKBOX_NONCE_SIZE];
547 csprng.fill_bytes(nonce.as_mut());
548
549 lockbox.push(version);
551 lockbox.push(lock_type.as_u8());
552 id.encode_vec(&mut lockbox);
553 lockbox.extend_from_slice(nonce.as_ref());
554 lockbox.extend_from_slice(content);
555
556 let (additional, nonce_and_content) = lockbox.split_at_mut(header_len);
558 let (_, content) = nonce_and_content.split_at_mut(nonce_len);
559 let aead = XChaCha20Poly1305::new_from_slice(&self.key).unwrap();
560 let nonce = XNonce::from(nonce);
561
562 let tag = aead
566 .encrypt_in_place_detached(&nonce, additional, content)
567 .expect("More data than the cipher can accept was put in");
568 lockbox.extend_from_slice(&tag);
569 lockbox
570 }
571
572 fn decrypt_lock_key(&self, lockbox: &LockLockboxRef) -> Result<LockKey, CryptoError> {
573 let recipient = lockbox.recipient();
574 let parts = lockbox.as_parts();
575 let mut key = self.decrypt_parts(&recipient, parts)?;
576 let result = BareLockKey::try_from(key.as_ref());
577 key.zeroize();
578 Ok(LockKey::from_interface(Arc::new(result?)))
579 }
580
581 fn decrypt_identity_key(
582 &self,
583 lockbox: &IdentityLockboxRef,
584 ) -> Result<IdentityKey, CryptoError> {
585 let recipient = lockbox.recipient();
586 let parts = lockbox.as_parts();
587 let mut key = self.decrypt_parts(&recipient, parts)?;
588 let result = BareIdKey::try_from(key.as_ref());
589 key.zeroize();
590 Ok(IdentityKey::from_interface(Arc::new(result?)))
591 }
592
593 fn decrypt_stream_key(&self, lockbox: &StreamLockboxRef) -> Result<StreamKey, CryptoError> {
594 let recipient = lockbox.recipient();
595 let parts = lockbox.as_parts();
596 let mut key = self.decrypt_parts(&recipient, parts)?;
597 let result = BareStreamKey::try_from(key.as_ref());
598 key.zeroize();
599 Ok(StreamKey::from_interface(Arc::new(result?)))
600 }
601
602 fn decrypt_data(&self, lockbox: &DataLockboxRef) -> Result<Vec<u8>, CryptoError> {
603 let recipient = lockbox.recipient();
604 let parts = lockbox.as_parts();
605 self.decrypt_parts(&recipient, parts)
606 }
607
608 fn self_export_lock(
609 &self,
610 csprng: &mut dyn CryptoSrc,
611 receive_lock: &LockId,
612 ) -> Option<StreamLockbox> {
613 let mut raw_secret = Vec::new(); self.encode_vec(&mut raw_secret);
615 let lockbox_vec = lock_id_encrypt(
616 receive_lock,
617 csprng,
618 LockboxType::Stream(false),
619 &raw_secret,
620 );
621 raw_secret.zeroize();
622 debug_assert!(raw_secret.iter().all(|&x| x == 0)); Some(stream_lockbox_from_parts(lockbox_vec))
624 }
625
626 fn self_export_stream(
627 &self,
628 csprng: &mut dyn CryptoSrc,
629 receive_stream: &StreamKey,
630 ) -> Option<StreamLockbox> {
631 let mut raw_secret = Vec::new(); self.encode_vec(&mut raw_secret);
633 let lockbox_vec = stream_key_encrypt(
634 receive_stream,
635 csprng,
636 LockboxType::Stream(true),
637 &raw_secret,
638 );
639 raw_secret.zeroize();
640 debug_assert!(raw_secret.iter().all(|&x| x == 0)); Some(stream_lockbox_from_parts(lockbox_vec))
642 }
643}
644
645#[derive(Clone, PartialEq, Eq, Hash)]
699pub struct StreamId {
700 inner: Vec<u8>,
701}
702
703impl StreamId {
704 pub fn version(&self) -> u8 {
705 self.inner[0]
706 }
707
708 pub fn raw_identifier(&self) -> &[u8] {
709 &self.inner[1..]
710 }
711
712 pub fn as_vec(&self) -> Vec<u8> {
715 let mut v = Vec::new();
716 self.encode_vec(&mut v);
717 v
718 }
719
720 pub fn to_base58(&self) -> String {
722 bs58::encode(&self.inner).into_string()
723 }
724
725 pub fn from_base58(s: &str) -> Result<Self, CryptoError> {
727 let raw = bs58::decode(s)
728 .into_vec()
729 .or(Err(CryptoError::BadFormat("Not valid Base58")))?;
730 Self::try_from(&raw[..])
731 }
732
733 pub fn encode_vec(&self, buf: &mut Vec<u8>) {
734 buf.reserve(self.size());
735 buf.extend_from_slice(&self.inner);
736 }
737
738 pub fn size(&self) -> usize {
739 self.inner.len()
740 }
741}
742
743impl TryFrom<&[u8]> for StreamId {
744 type Error = CryptoError;
745 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
748 let _version = value.first().ok_or(CryptoError::BadLength {
749 step: "get stream version",
750 actual: 0,
751 expected: 1,
752 })?;
753 let expected_len = 33;
754 if value.len() != expected_len {
755 return Err(CryptoError::BadLength {
756 step: "get stream id",
757 actual: value.len(),
758 expected: expected_len,
759 });
760 }
761 Ok(Self {
762 inner: Vec::from(value),
763 })
764 }
765}
766
767impl fmt::Debug for StreamId {
768 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
769 let (version, id_bytes) = self.inner.split_first().unwrap();
770 f.debug_struct("Identity")
771 .field("version", version)
772 .field("stream_id", &id_bytes)
773 .finish()
774 }
775}
776
777impl fmt::Display for StreamId {
778 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
780 write!(f, "{}", self.to_base58())
781 }
782}
783
784impl fmt::LowerHex for StreamId {
785 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
786 for byte in self.inner.iter() {
787 write!(f, "{:x}", byte)?;
788 }
789 Ok(())
790 }
791}
792
793impl fmt::UpperHex for StreamId {
794 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
795 for byte in self.inner.iter() {
796 write!(f, "{:X}", byte)?;
797 }
798 Ok(())
799 }
800}
801
802#[cfg(test)]
803mod tests {
804 use super::*;
805 use crate::lockbox::LockboxRecipient;
806
807 #[test]
808 fn basics() {
809 let mut csprng = rand::rngs::OsRng;
810 let key = StreamKey::with_rng(&mut csprng);
811 assert_eq!(key.version(), DEFAULT_STREAM_VERSION);
812 let key = StreamKey::with_rng_and_version(&mut csprng, DEFAULT_STREAM_VERSION).unwrap();
813 assert_eq!(key.version(), DEFAULT_STREAM_VERSION);
814 let result = StreamKey::with_rng_and_version(&mut csprng, 99u8);
815 if let Err(CryptoError::UnsupportedVersion(99u8)) = result {
816 } else {
817 panic!("Didn't get expected error on new_temp_with_version");
818 }
819 }
820
821 #[test]
822 fn display() {
823 let key = StreamKey::new();
824 let disp_key = format!("{}", &key);
825 let disp_id = format!("{}", key.id());
826 let base58 = key.id().to_base58();
827 assert_eq!(disp_key, disp_id);
828 assert_eq!(disp_key, base58);
829 assert!(disp_key.len() > 1);
830 }
831
832 #[test]
833 fn id_sanity_check() {
834 let key = BareStreamKey::new();
837 let id = key.id();
838 let mut enc_key = Vec::new();
839 let mut enc_id = Vec::new();
840 key.encode_vec(&mut enc_key);
841 id.encode_vec(&mut enc_id);
842 assert_ne!(enc_id, enc_key);
843 }
844
845 #[test]
846 fn base58() {
847 let key = StreamKey::new();
848 let mut base58 = key.id().to_base58();
849 assert!(base58.len() > 1);
850 let id = StreamId::from_base58(&base58).unwrap();
851 assert_eq!(&id, key.id());
852 base58.push('a');
853 base58.push('a');
854 assert!(StreamId::from_base58(&base58).is_err());
855 base58.pop();
856 base58.pop();
857 base58.pop();
858 assert!(StreamId::from_base58(&base58).is_err());
859 }
860
861 #[test]
862 fn encode() {
863 let key = StreamKey::new();
864 let id = key.id();
865 let mut id_vec = Vec::new();
866 id.encode_vec(&mut id_vec);
867 assert_eq!(id_vec.len(), id.size());
868 let id = StreamId::try_from(&id_vec[..]).unwrap();
869 assert_eq!(&id, key.id());
870 }
871
872 fn corrupt_version<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
873 where
874 F1: Fn(&[u8]) -> bool,
875 F2: Fn(&[u8]) -> bool,
876 {
877 let version = enc[0];
879 enc[0] = 0;
880 assert!(!check_decode(&enc[..]));
881 enc[0] = 2;
882 assert!(!check_decode(&enc[..]));
883 enc[0] = version;
884 assert!(check_decrypt(&enc[..]));
885 }
886
887 fn corrupt_type<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
888 where
889 F1: Fn(&[u8]) -> bool,
890 F2: Fn(&[u8]) -> bool,
891 {
892 enc[1] |= 0x80;
894 assert!(!check_decode(&enc[..]));
895 enc[1] &= 0x07;
896 assert!(check_decrypt(&enc[..]));
897 for _ in 0..6 {
898 enc[1] = (enc[1] + 1) & 0x7;
900 assert!(!check_decode(&enc[..]));
901 }
902 enc[1] = (enc[1] + 1) & 0x7; assert!(check_decode(&enc[..]));
904 assert!(!check_decrypt(&enc[..]));
905 enc[1] = (enc[1] + 1) & 0x7;
907 assert!(check_decrypt(&enc[..]));
908 }
909
910 fn corrupt_id<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
911 where
912 F1: Fn(&[u8]) -> bool,
913 F2: Fn(&[u8]) -> bool,
914 {
915 enc[2] = 0;
917 assert!(!check_decode(&enc[..]));
918 enc[2] = 2;
919 assert!(!check_decode(&enc[..]));
920 enc[2] = DEFAULT_STREAM_VERSION;
921 assert!(check_decrypt(&enc[..]));
922 enc[3] ^= 0xFF;
923 assert!(!check_decrypt(&enc[..]));
924 enc[3] ^= 0xFF;
925 assert!(check_decrypt(&enc[..]));
926 }
927
928 fn corrupt_nonce<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
929 where
930 F1: Fn(&[u8]) -> bool,
931 F2: Fn(&[u8]) -> bool,
932 {
933 enc[35] ^= 0xFF;
935 assert!(check_decode(&enc[..]));
936 assert!(!check_decrypt(&enc[..]));
937 enc[35] ^= 0xFF;
938 assert!(check_decrypt(&enc[..]));
939 }
940
941 fn corrupt_ciphertext<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
942 where
943 F1: Fn(&[u8]) -> bool,
944 F2: Fn(&[u8]) -> bool,
945 {
946 enc[59] ^= 0xFF;
948 assert!(check_decode(&enc[..]));
949 assert!(!check_decrypt(&enc[..]));
950 enc[59] ^= 0xFF;
951 assert!(check_decrypt(&enc[..]));
952 }
953
954 fn corrupt_tag<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
955 where
956 F1: Fn(&[u8]) -> bool,
957 F2: Fn(&[u8]) -> bool,
958 {
959 let tag_end = enc.last_mut().unwrap();
961 *tag_end ^= 0xFF;
962 assert!(check_decode(&enc[..]));
963 assert!(!check_decrypt(&enc[..]));
964 let tag_end = enc.last_mut().unwrap();
965 *tag_end ^= 0xFF;
966 assert!(check_decrypt(&enc[..]));
967 }
968
969 fn corrupt_length_extend<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
970 where
971 F1: Fn(&[u8]) -> bool,
972 F2: Fn(&[u8]) -> bool,
973 {
974 enc.push(0);
976 assert!(check_decode(&enc[..]));
977 assert!(!check_decrypt(&enc[..]));
978 enc.pop();
979 assert!(check_decrypt(&enc[..]));
980 }
981
982 fn corrupt_truncation<F1, F2>(mut enc: Vec<u8>, check_decode: F1, check_decrypt: F2)
983 where
984 F1: Fn(&[u8]) -> bool,
985 F2: Fn(&[u8]) -> bool,
986 {
987 enc.pop();
989 assert!(check_decode(&enc[..]));
990 assert!(!check_decrypt(&enc[..]));
991 }
992
993 fn corrupt_each_byte<F1, F2>(mut enc: Vec<u8>, _check_decode: F1, check_decrypt: F2)
994 where
995 F1: Fn(&[u8]) -> bool,
996 F2: Fn(&[u8]) -> bool,
997 {
998 for i in 0..enc.len() {
999 enc[i] ^= 0xFF;
1000 assert!(!check_decrypt(&enc[..]));
1001 enc[i] ^= 0xFF;
1002 }
1003 }
1004
1005 fn corrupt_inner_version<F: Fn(&[u8]) -> bool>(mut content: Vec<u8>, check_sequence: F) {
1006 content[0] = 0u8;
1008 assert!(!check_sequence(&content[..]));
1009 content[0] = 99u8;
1011 assert!(!check_sequence(&content[..]));
1012 }
1013
1014 fn corrupt_inner_length_extend<F: Fn(&[u8]) -> bool>(mut content: Vec<u8>, check_sequence: F) {
1015 content.push(0u8);
1016 assert!(!check_sequence(&content[..]));
1017 }
1018
1019 fn corrupt_inner_truncate<F: Fn(&[u8]) -> bool>(mut content: Vec<u8>, check_sequence: F) {
1020 content.pop();
1021 assert!(!check_sequence(&content[..]));
1022 }
1023
1024 fn setup_data() -> (Vec<u8>, impl Fn(&[u8]) -> bool, impl Fn(&[u8]) -> bool) {
1025 let key = StreamKey::new();
1027 let message = b"I am a test message, going undercover";
1028
1029 let lockbox = key.encrypt_data(message);
1031 let recipient = LockboxRecipient::StreamId(key.id().clone());
1032 assert_eq!(recipient, lockbox.recipient());
1033 let enc = Vec::from(lockbox.as_bytes());
1034 (
1035 enc,
1036 |enc| DataLockboxRef::from_bytes(enc).is_ok(),
1037 move |enc| {
1038 let dec_lockbox = if let Ok(d) = DataLockboxRef::from_bytes(enc) {
1039 d
1040 } else {
1041 return false;
1042 };
1043 if LockboxRecipient::StreamId(key.id().clone()) != dec_lockbox.recipient() {
1044 return false;
1045 }
1046 if let Ok(dec) = key.decrypt_data(dec_lockbox) {
1047 dec == message
1048 } else {
1049 false
1050 }
1051 },
1052 )
1053 }
1054
1055 #[test]
1056 fn data_clean_decrypt() {
1057 let (enc, _check_decode, check_decrypt) = setup_data();
1058 assert!(check_decrypt(&enc[..]));
1059 }
1060
1061 #[test]
1062 fn data_corrupt_version() {
1063 let (enc, check_decode, check_decrypt) = setup_data();
1064 corrupt_version(enc, check_decode, check_decrypt);
1065 }
1066
1067 #[test]
1068 fn data_corrupt_type() {
1069 let (enc, check_decode, check_decrypt) = setup_data();
1070 corrupt_type(enc, check_decode, check_decrypt);
1071 }
1072
1073 #[test]
1074 fn data_corrupt_id() {
1075 let (enc, check_decode, check_decrypt) = setup_data();
1076 corrupt_id(enc, check_decode, check_decrypt);
1077 }
1078
1079 #[test]
1080 fn data_corrupt_nonce() {
1081 let (enc, check_decode, check_decrypt) = setup_data();
1082 corrupt_nonce(enc, check_decode, check_decrypt);
1083 }
1084
1085 #[test]
1086 fn data_corrupt_ciphertext() {
1087 let (enc, check_decode, check_decrypt) = setup_data();
1088 corrupt_ciphertext(enc, check_decode, check_decrypt);
1089 }
1090
1091 #[test]
1092 fn data_corrupt_tag() {
1093 let (enc, check_decode, check_decrypt) = setup_data();
1094 corrupt_tag(enc, check_decode, check_decrypt);
1095 }
1096
1097 #[test]
1098 fn data_corrupt_length_extend() {
1099 let (enc, check_decode, check_decrypt) = setup_data();
1100 corrupt_length_extend(enc, check_decode, check_decrypt);
1101 }
1102
1103 #[test]
1104 fn data_corrupt_truncation() {
1105 let (enc, check_decode, check_decrypt) = setup_data();
1106 corrupt_truncation(enc, check_decode, check_decrypt);
1107 }
1108
1109 #[test]
1110 fn data_corrupt_each_byte() {
1111 let (enc, check_decode, check_decrypt) = setup_data();
1112 corrupt_each_byte(enc, check_decode, check_decrypt);
1113 }
1114
1115 fn setup_id() -> (Vec<u8>, impl Fn(&[u8]) -> bool, impl Fn(&[u8]) -> bool) {
1116 let key = StreamKey::new();
1118 let to_send = IdentityKey::new();
1119
1120 let lockbox = to_send.export_for_stream(&key).unwrap();
1122 let recipient = LockboxRecipient::StreamId(key.id().clone());
1123 assert_eq!(recipient, lockbox.recipient());
1124 let enc = Vec::from(lockbox.as_bytes());
1125 (
1126 enc,
1127 |enc| IdentityLockboxRef::from_bytes(enc).is_ok(),
1128 move |enc| {
1129 let dec_lockbox = if let Ok(d) = IdentityLockboxRef::from_bytes(enc) {
1130 d
1131 } else {
1132 return false;
1133 };
1134 if LockboxRecipient::StreamId(key.id().clone()) != dec_lockbox.recipient() {
1135 return false;
1136 }
1137 if let Ok(dec) = key.decrypt_identity_key(dec_lockbox) {
1138 dec.id() == to_send.id()
1139 } else {
1140 false
1141 }
1142 },
1143 )
1144 }
1145
1146 #[test]
1147 fn id_clean_decrypt() {
1148 let (enc, _check_decode, check_decrypt) = setup_id();
1149 assert!(check_decrypt(&enc[..]));
1150 }
1151
1152 #[test]
1153 fn id_corrupt_version() {
1154 let (enc, check_decode, check_decrypt) = setup_id();
1155 corrupt_version(enc, check_decode, check_decrypt);
1156 }
1157
1158 #[test]
1159 fn id_corrupt_type() {
1160 let (enc, check_decode, check_decrypt) = setup_id();
1161 corrupt_type(enc, check_decode, check_decrypt);
1162 }
1163
1164 #[test]
1165 fn id_corrupt_id() {
1166 let (enc, check_decode, check_decrypt) = setup_id();
1167 corrupt_id(enc, check_decode, check_decrypt);
1168 }
1169
1170 #[test]
1171 fn id_corrupt_nonce() {
1172 let (enc, check_decode, check_decrypt) = setup_id();
1173 corrupt_nonce(enc, check_decode, check_decrypt);
1174 }
1175
1176 #[test]
1177 fn id_corrupt_ciphertext() {
1178 let (enc, check_decode, check_decrypt) = setup_id();
1179 corrupt_ciphertext(enc, check_decode, check_decrypt);
1180 }
1181
1182 #[test]
1183 fn id_corrupt_tag() {
1184 let (enc, check_decode, check_decrypt) = setup_id();
1185 corrupt_tag(enc, check_decode, check_decrypt);
1186 }
1187
1188 #[test]
1189 fn id_corrupt_length_extend() {
1190 let (enc, check_decode, check_decrypt) = setup_id();
1191 corrupt_length_extend(enc, check_decode, check_decrypt);
1192 }
1193
1194 #[test]
1195 fn id_corrupt_truncation() {
1196 let (enc, check_decode, check_decrypt) = setup_id();
1197 corrupt_truncation(enc, check_decode, check_decrypt);
1198 }
1199
1200 #[test]
1201 fn id_corrupt_each_byte() {
1202 let (enc, check_decode, check_decrypt) = setup_id();
1203 corrupt_each_byte(enc, check_decode, check_decrypt);
1204 }
1205
1206 fn setup_id_raw() -> (Vec<u8>, impl Fn(&[u8]) -> bool) {
1207 use crate::identity::SignInterface;
1208 let key = StreamKey::new();
1210 let to_send = crate::BareIdKey::new();
1211
1212 let mut content = Vec::new();
1214 to_send.encode_vec(&mut content);
1215
1216 (content, move |content| {
1217 let mut csprng = rand::rngs::OsRng;
1218 let lockbox = identity_lockbox_from_parts(stream_key_encrypt(
1219 &key,
1220 &mut csprng,
1221 crate::lockbox::LockboxType::Identity(true),
1222 content,
1223 ));
1224 let enc = Vec::from(lockbox.as_bytes());
1225 let lockbox = if let Ok(l) = IdentityLockboxRef::from_bytes(&enc[..]) {
1226 l
1227 } else {
1228 return false;
1229 };
1230 if let Ok(dec) = key.decrypt_identity_key(lockbox) {
1231 dec.id() == to_send.id()
1232 } else {
1233 false
1234 }
1235 })
1236 }
1237
1238 #[test]
1239 fn id_inner_ok() {
1240 let (content, check_sequence) = setup_id_raw();
1241 assert!(check_sequence(&content[..]));
1242 }
1243
1244 #[test]
1245 fn id_corrupt_inner_version() {
1246 let (content, check_sequence) = setup_id_raw();
1247 corrupt_inner_version(content, check_sequence);
1248 }
1249
1250 #[test]
1251 fn id_corrupt_inner_length_extend() {
1252 let (content, check_sequence) = setup_id_raw();
1253 corrupt_inner_length_extend(content, check_sequence);
1254 }
1255
1256 #[test]
1257 fn id_corrupt_inner_truncate() {
1258 let (content, check_sequence) = setup_id_raw();
1259 corrupt_inner_truncate(content, check_sequence);
1260 }
1261
1262 fn setup_stream() -> (Vec<u8>, impl Fn(&[u8]) -> bool, impl Fn(&[u8]) -> bool) {
1263 let key = StreamKey::new();
1265 let to_send = StreamKey::new();
1266
1267 let lockbox = to_send.export_for_stream(&key).unwrap();
1269 let recipient = LockboxRecipient::StreamId(key.id().clone());
1270 assert_eq!(recipient, lockbox.recipient());
1271 let enc = Vec::from(lockbox.as_bytes());
1272 (
1273 enc,
1274 |enc| StreamLockboxRef::from_bytes(enc).is_ok(),
1275 move |enc| {
1276 let dec_lockbox = if let Ok(d) = StreamLockboxRef::from_bytes(enc) {
1277 d
1278 } else {
1279 return false;
1280 };
1281 if LockboxRecipient::StreamId(key.id().clone()) != dec_lockbox.recipient() {
1282 return false;
1283 }
1284 if let Ok(dec) = key.decrypt_stream_key(dec_lockbox) {
1285 dec.id() == to_send.id()
1286 } else {
1287 false
1288 }
1289 },
1290 )
1291 }
1292
1293 #[test]
1294 fn lock_stream_clean_decrypt() {
1295 let (enc, _check_decode, check_decrypt) = setup_stream();
1296 assert!(check_decrypt(&enc[..]));
1297 }
1298
1299 #[test]
1300 fn lock_stream_corrupt_version() {
1301 let (enc, check_decode, check_decrypt) = setup_stream();
1302 corrupt_version(enc, check_decode, check_decrypt);
1303 }
1304
1305 #[test]
1306 fn lock_stream_corrupt_type() {
1307 let (enc, check_decode, check_decrypt) = setup_stream();
1308 corrupt_type(enc, check_decode, check_decrypt);
1309 }
1310
1311 #[test]
1312 fn lock_stream_corrupt_id() {
1313 let (enc, check_decode, check_decrypt) = setup_stream();
1314 corrupt_id(enc, check_decode, check_decrypt);
1315 }
1316
1317 #[test]
1318 fn lock_stream_corrupt_nonce() {
1319 let (enc, check_decode, check_decrypt) = setup_stream();
1320 corrupt_nonce(enc, check_decode, check_decrypt);
1321 }
1322
1323 #[test]
1324 fn lock_stream_corrupt_ciphertext() {
1325 let (enc, check_decode, check_decrypt) = setup_stream();
1326 corrupt_ciphertext(enc, check_decode, check_decrypt);
1327 }
1328
1329 #[test]
1330 fn lock_stream_corrupt_tag() {
1331 let (enc, check_decode, check_decrypt) = setup_stream();
1332 corrupt_tag(enc, check_decode, check_decrypt);
1333 }
1334
1335 #[test]
1336 fn lock_stream_corrupt_length_extend() {
1337 let (enc, check_decode, check_decrypt) = setup_stream();
1338 corrupt_length_extend(enc, check_decode, check_decrypt);
1339 }
1340
1341 #[test]
1342 fn lock_stream_corrupt_truncation() {
1343 let (enc, check_decode, check_decrypt) = setup_stream();
1344 corrupt_truncation(enc, check_decode, check_decrypt);
1345 }
1346
1347 #[test]
1348 fn lock_stream_corrupt_each_byte() {
1349 let (enc, check_decode, check_decrypt) = setup_stream();
1350 corrupt_each_byte(enc, check_decode, check_decrypt);
1351 }
1352
1353 fn setup_stream_raw() -> (Vec<u8>, impl Fn(&[u8]) -> bool) {
1354 let key = StreamKey::new();
1356 let to_send = crate::BareStreamKey::new();
1357
1358 let mut content = Vec::new();
1360 to_send.encode_vec(&mut content);
1361
1362 (content, move |content| {
1363 let mut csprng = rand::rngs::OsRng;
1364 let lockbox = stream_lockbox_from_parts(stream_key_encrypt(
1365 &key,
1366 &mut csprng,
1367 crate::lockbox::LockboxType::Stream(true),
1368 content,
1369 ));
1370 let enc = Vec::from(lockbox.as_bytes());
1371 let lockbox = if let Ok(l) = StreamLockboxRef::from_bytes(&enc[..]) {
1372 l
1373 } else {
1374 return false;
1375 };
1376 if let Ok(dec) = key.decrypt_stream_key(lockbox) {
1377 dec.id() == to_send.id()
1378 } else {
1379 false
1380 }
1381 })
1382 }
1383
1384 #[test]
1385 fn lock_stream_inner_ok() {
1386 let (content, check_sequence) = setup_stream_raw();
1387 assert!(check_sequence(&content[..]));
1388 }
1389
1390 #[test]
1391 fn lock_stream_corrupt_inner_version() {
1392 let (content, check_sequence) = setup_stream_raw();
1393 corrupt_inner_version(content, check_sequence);
1394 }
1395
1396 #[test]
1397 fn lock_stream_corrupt_inner_length_extend() {
1398 let (content, check_sequence) = setup_stream_raw();
1399 corrupt_inner_length_extend(content, check_sequence);
1400 }
1401
1402 #[test]
1403 fn lock_stream_corrupt_inner_truncate() {
1404 let (content, check_sequence) = setup_stream_raw();
1405 corrupt_inner_truncate(content, check_sequence);
1406 }
1407
1408 fn setup_lock() -> (Vec<u8>, impl Fn(&[u8]) -> bool, impl Fn(&[u8]) -> bool) {
1409 let key = StreamKey::new();
1411 let to_send = LockKey::new();
1412
1413 let lockbox = to_send.export_for_stream(&key).unwrap();
1415 let recipient = LockboxRecipient::StreamId(key.id().clone());
1416 assert_eq!(recipient, lockbox.recipient());
1417 let enc = Vec::from(lockbox.as_bytes());
1418 (
1419 enc,
1420 |enc| LockLockboxRef::from_bytes(enc).is_ok(),
1421 move |enc| {
1422 let dec_lockbox = if let Ok(d) = LockLockboxRef::from_bytes(enc) {
1423 d
1424 } else {
1425 return false;
1426 };
1427 if LockboxRecipient::StreamId(key.id().clone()) != dec_lockbox.recipient() {
1428 return false;
1429 }
1430 if let Ok(dec) = key.decrypt_lock_key(dec_lockbox) {
1431 dec.id() == to_send.id()
1432 } else {
1433 false
1434 }
1435 },
1436 )
1437 }
1438
1439 #[test]
1440 fn lock_lock_clean_decrypt() {
1441 let (enc, _check_decode, check_decrypt) = setup_lock();
1442 assert!(check_decrypt(&enc[..]));
1443 }
1444
1445 #[test]
1446 fn lock_lock_corrupt_version() {
1447 let (enc, check_decode, check_decrypt) = setup_lock();
1448 corrupt_version(enc, check_decode, check_decrypt);
1449 }
1450
1451 #[test]
1452 fn lock_lock_corrupt_type() {
1453 let (enc, check_decode, check_decrypt) = setup_lock();
1454 corrupt_type(enc, check_decode, check_decrypt);
1455 }
1456
1457 #[test]
1458 fn lock_lock_corrupt_id() {
1459 let (enc, check_decode, check_decrypt) = setup_lock();
1460 corrupt_id(enc, check_decode, check_decrypt);
1461 }
1462
1463 #[test]
1464 fn lock_lock_corrupt_nonce() {
1465 let (enc, check_decode, check_decrypt) = setup_lock();
1466 corrupt_nonce(enc, check_decode, check_decrypt);
1467 }
1468
1469 #[test]
1470 fn lock_lock_corrupt_ciphertext() {
1471 let (enc, check_decode, check_decrypt) = setup_lock();
1472 corrupt_ciphertext(enc, check_decode, check_decrypt);
1473 }
1474
1475 #[test]
1476 fn lock_lock_corrupt_tag() {
1477 let (enc, check_decode, check_decrypt) = setup_lock();
1478 corrupt_tag(enc, check_decode, check_decrypt);
1479 }
1480
1481 #[test]
1482 fn lock_lock_corrupt_length_extend() {
1483 let (enc, check_decode, check_decrypt) = setup_lock();
1484 corrupt_length_extend(enc, check_decode, check_decrypt);
1485 }
1486
1487 #[test]
1488 fn lock_lock_corrupt_truncation() {
1489 let (enc, check_decode, check_decrypt) = setup_lock();
1490 corrupt_truncation(enc, check_decode, check_decrypt);
1491 }
1492
1493 #[test]
1494 fn lock_lock_corrupt_each_byte() {
1495 let (enc, check_decode, check_decrypt) = setup_lock();
1496 corrupt_each_byte(enc, check_decode, check_decrypt);
1497 }
1498
1499 fn setup_lock_raw() -> (Vec<u8>, impl Fn(&[u8]) -> bool) {
1500 use crate::lock::LockInterface;
1501 let key = StreamKey::new();
1503 let to_send = crate::BareLockKey::new();
1504
1505 let mut content = Vec::new();
1507 to_send.encode_vec(&mut content);
1508
1509 (content, move |content| {
1510 let mut csprng = rand::rngs::OsRng;
1511 let lockbox = lock_lockbox_from_parts(stream_key_encrypt(
1512 &key,
1513 &mut csprng,
1514 crate::lockbox::LockboxType::Lock(true),
1515 content,
1516 ));
1517 let enc = Vec::from(lockbox.as_bytes());
1518 let lockbox = if let Ok(l) = LockLockboxRef::from_bytes(&enc[..]) {
1519 l
1520 } else {
1521 return false;
1522 };
1523 if let Ok(dec) = key.decrypt_lock_key(lockbox) {
1524 dec.id() == to_send.id()
1525 } else {
1526 false
1527 }
1528 })
1529 }
1530
1531 #[test]
1532 fn lock_lock_inner_ok() {
1533 let (content, check_sequence) = setup_lock_raw();
1534 assert!(check_sequence(&content[..]));
1535 }
1536
1537 #[test]
1538 fn lock_lock_corrupt_inner_version() {
1539 let (content, check_sequence) = setup_lock_raw();
1540 corrupt_inner_version(content, check_sequence);
1541 }
1542
1543 #[test]
1544 fn lock_lock_corrupt_inner_length_extend() {
1545 let (content, check_sequence) = setup_lock_raw();
1546 corrupt_inner_length_extend(content, check_sequence);
1547 }
1548
1549 #[test]
1550 fn lock_lock_corrupt_inner_truncate() {
1551 let (content, check_sequence) = setup_lock_raw();
1552 corrupt_inner_truncate(content, check_sequence);
1553 }
1554}