fog_crypto/
stream.rs

1//! Symmetric-Key encryption.
2//!
3//! This submodule provides a `StreamKey` for symmetric encryption & decryption of any lockbox
4//! type. Each `StreamKey` has a corresponding `StreamId` for easily identifying the key needed to
5//! decrypt a lockbox.
6//!
7//! # Example
8//!
9//! ```
10//! # use fog_crypto::stream::*;
11//! # use fog_crypto::lockbox::*;
12//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
13//!
14//! // Make a new temporary key
15//! let key = StreamKey::new();
16//! let id = key.id().clone();
17//!
18//! println!("StreamId(Base58): {}", key.id());
19//!
20//! // Encrypt some data with the key, then turn it into a byte vector
21//! let data = b"I am sensitive information, about to be encrypted";
22//! let lockbox = key.encrypt_data(data.as_ref());
23//! let mut encoded = Vec::new();
24//! encoded.extend_from_slice(lockbox.as_bytes());
25//!
26//! // Decrypt that data with the same key
27//! let dec_lockbox = DataLockboxRef::from_bytes(encoded.as_ref())?;
28//! let dec_data = key.decrypt_data(&dec_lockbox)?;
29//! # Ok(())
30//! # }
31//! ```
32//!
33//! # Algorithms
34//!
35//! The current (and only) algorithm for symmetric encryption is XChaCha20 with a Poly1305 AEAD
36//! construction (XChaCha20Poly1305).
37//!
38//! The `StreamId` is computed by taking the 32-byte secret key and hashing it with BLAKE2b, with
39//! the parameters: no key, no salt, and a persona set to "fog-crypto-sid". 32 bytes of the output
40//! hash are used to create the `StreamId`.
41//!
42//! # Format
43//!
44//! A `StreamId` is encoded as a version byte followed by the key itself, whose length is dependant
45//! on the version. For XChaCha20Poly1305, it is 32 bytes plus the version byte.
46//!
47//! A `StreamKey` is also encoded as a version byte followed by the key itself, whose length is
48//! dependant on the version. For XChaCha20Poly1305, it is 32 bytes plus the version byte. This
49//! encoding is only ever used for the payload of a [`StreamLockbox`].
50//!
51//! See the [`lockbox`](crate::lockbox) module for documentation on the encoding format for
52//! encrypted payloads.
53
54use 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
73/// Default symmetric-key encryption algorithm version.
74pub const DEFAULT_STREAM_VERSION: u8 = 1;
75
76/// Minimum accepted symmetric-key encryption algorithm version.
77pub const MIN_STREAM_VERSION: u8 = 1;
78
79/// Maximum accepted symmetric-key encryption algorithm version.
80pub const MAX_STREAM_VERSION: u8 = 1;
81
82const V1_STREAM_ID_SIZE: usize = 32;
83const V1_STREAM_KEY_SIZE: usize = 32;
84
85/// Get expected size of StreamId for a given version. Version *must* be validated before calling
86/// this.
87pub(crate) fn stream_id_size(_version: u8) -> usize {
88    1 + V1_STREAM_ID_SIZE
89}
90
91/// Stream Key that allows encrypting data into a `Lockbox` and decrypting it later.
92///
93/// This acts as a wrapper for a specific cryptographic symmetric key, which can only be used with
94/// the corresponding symmetric encryption algorithm. The underlying key may be located in a
95/// hardware module or some other private keystore; in this case, it may be impossible to export
96/// the key.
97///
98/// ```
99/// # use std::convert::TryFrom;
100/// # use fog_crypto::stream::*;
101/// # use fog_crypto::lockbox::*;
102/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
103///
104/// // Make a new temporary key
105/// let key = StreamKey::new();
106/// let id = key.id().clone();
107///
108/// // Encrypt some data with the key, then turn it into a byte vector
109/// let data = b"I am sensitive information, about to be encrypted";
110/// let lockbox = key.encrypt_data(data.as_ref());
111/// let mut encoded = Vec::new();
112/// encoded.extend_from_slice(lockbox.as_bytes());
113///
114/// // Decrypt that data with the same key
115/// let dec_lockbox = DataLockboxRef::from_bytes(encoded.as_ref())?;
116/// let dec_data = key.decrypt_data(dec_lockbox)?;
117/// # Ok(())
118/// # }
119/// ```
120#[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    /// Create a new `StreamKey` to hold a `StreamInterface` implementation. Can be used by
135    /// implementors of a vault when making new `StreamKey` instances.
136    pub fn from_interface(interface: Arc<dyn StreamInterface>) -> Self {
137        StreamKey { interface }
138    }
139
140    /// Generate a temporary `StreamKey` that exists only in program memory.
141    #[cfg(feature = "getrandom")]
142    pub fn new() -> StreamKey {
143        let interface = Arc::new(BareStreamKey::new());
144        Self::from_interface(interface)
145    }
146
147    /// Generate a temporary `StreamKey` that exists only in program memory,
148    /// using the provided cryptographic RNG.
149    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    /// Generate a temporary `StreamKey` that exists only in program memory. Uses the specified
158    /// version instead of the default, and fails if the version is unsupported.
159    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    /// Version of symmetric encryption algorithm used by this key.
168    pub fn version(&self) -> u8 {
169        self.interface.id().version()
170    }
171
172    /// The publically shareable identifier for this key.
173    pub fn id(&self) -> &StreamId {
174        self.interface.id()
175    }
176
177    #[cfg(feature = "getrandom")]
178    /// Encrypt a byte slice into a `DataLockbox`.
179    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    /// Encrypt a byte slice into a `DataLockbox`. Requires a cryptographic RNG to generate the
187    /// needed nonce.
188    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    /// Attempt to decrypt a `LockLockboxRef` with this key. On success, the returned `LockKey` is
200    /// temporary and not associated with any Vault.
201    pub fn decrypt_lock_key(&self, lockbox: &LockLockboxRef) -> Result<LockKey, CryptoError> {
202        self.interface.decrypt_lock_key(lockbox)
203    }
204
205    /// Attempt to decrypt a `IdentityLockboxRef` with this key. On success, the returned
206    /// `IdentityKey` is temporary and not associated with any Vault.
207    pub fn decrypt_identity_key(
208        &self,
209        lockbox: &IdentityLockboxRef,
210    ) -> Result<IdentityKey, CryptoError> {
211        self.interface.decrypt_identity_key(lockbox)
212    }
213
214    /// Attempt to decrypt a `StreamLockboxRef` with this key. On success, the returned
215    /// `StreamKey` is temporary and not associated with any Vault.
216    pub fn decrypt_stream_key(&self, lockbox: &StreamLockboxRef) -> Result<StreamKey, CryptoError> {
217        self.interface.decrypt_stream_key(lockbox)
218    }
219
220    /// Attempt to decrypt a `DataLockboxRef` with this key.
221    pub fn decrypt_data(&self, lockbox: &DataLockboxRef) -> Result<Vec<u8>, CryptoError> {
222        self.interface.decrypt_data(lockbox)
223    }
224
225    /// Pack this secret into a `StreamLockbox`, meant for the recipient specified by `id`. Returns
226    /// None if this key cannot be exported.
227    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    /// Pack this secret into a `StreamLockbox`, meant for the recipient specified by `id`. Returns
235    /// None if this key cannot be exported.
236    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    /// Pack this key into a `StreamLockbox`, meant for the recipient specified by `stream`. Returns
246    /// None if this key cannot be exported for the given recipient. Generally, the recipient
247    /// should be in the same Vault as the key being exported, or the exported key should be a
248    /// temporary key.
249    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    /// Pack this key into a `StreamLockbox`, meant for the recipient specified by `stream`. Returns
257    /// None if this key cannot be exported for the given recipient. Generally, the recipient
258    /// should be in the same Vault as the key being exported, or the exported key should be a
259    /// temporary key.
260    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
269/// Encrypt data with a `StreamKey`, returning a raw byte vector. Implementors of the
270/// StreamInterface can use this when building various lockboxes without it showing up in the
271/// regular StreamKey interface.
272pub 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    /// Display just the StreamId (never the underlying key).
292    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
303/// A symmetric encryption/decryption interface, implemented by anything that can hold a symmetric
304/// encryption key.
305///
306/// An implementor must handle all supported symmetric-key encryption algorithms.
307pub trait StreamInterface: Sync + Send {
308    /// Get the corresponding `StreamId` for the symmetric key.
309    fn id(&self) -> &StreamId;
310
311    /// Encrypt raw data into a lockbox, following the `StreamKey`-recipient lockbox format (see
312    /// [`lockbox`](crate::lockbox).
313    fn encrypt(
314        &self,
315        csprng: &mut dyn CryptoSrc,
316        lock_type: LockboxType,
317        content: &[u8],
318    ) -> Vec<u8>;
319
320    /// Decrypt a `LockLockboxRef` and return a temporary (not stored in Vault) LockKey on success.
321    fn decrypt_lock_key(&self, lockbox: &LockLockboxRef) -> Result<LockKey, CryptoError>;
322
323    /// Decrypt a `IdentityLockboxRef` and return a temporary (not stored in Vault) `IdentityKey` on
324    /// success.
325    fn decrypt_identity_key(
326        &self,
327        lockbox: &IdentityLockboxRef,
328    ) -> Result<IdentityKey, CryptoError>;
329
330    /// Decrypt a `StreamLockboxRef` and return a temporary (not stored in Vault) `StreamKey` on
331    /// success.
332    fn decrypt_stream_key(&self, lockbox: &StreamLockboxRef) -> Result<StreamKey, CryptoError>;
333
334    /// Decrypt a `DataLockboxRef` and return a the decoded raw data on success.
335    fn decrypt_data(&self, lockbox: &DataLockboxRef) -> Result<Vec<u8>, CryptoError>;
336
337    /// Export the symmetric key in a `StreamLockbox`, with `receive_lock` as the recipient. If the
338    /// key cannot be exported, this should return None.
339    fn self_export_lock(
340        &self,
341        csprng: &mut dyn CryptoSrc,
342        receive_lock: &LockId,
343    ) -> Option<StreamLockbox>;
344
345    /// Export the symmetric key in a `StreamLockbox`, with `receive_stream` as the recipient. If
346    /// the key cannot be exported, this should return None. Additionally, if the underlying
347    /// implementation does not allow moving the raw key into memory (i.e. it cannot call
348    /// [`StreamInterface::encrypt`] or
349    /// [`lock_id_encrypt`](crate::lock::lock_id_encrypt)) then None can also be
350    /// returned.
351    fn self_export_stream(
352        &self,
353        csprng: &mut dyn CryptoSrc,
354        receive_stream: &StreamKey,
355    ) -> Option<StreamLockbox>;
356}
357
358/// Compute the corresponding StreamId for a given raw key.
359pub 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
372/// A self-contained implementor of `StreamInterface`. It's expected this will be used unless the
373/// symmetric key is being managed by the OS or a hardware module.
374pub 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    /// Generate a new random key.
389    #[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    /// Generate a new key, given a cryptographic RNG.
404    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    /// Generate a new key with a specific version, given a cryptographic RNG. Fails if the version
412    /// isn't supported.
413    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        // Wipe out the key after it's copied into the struct
429        key.zeroize();
430        // I'm real paranoid about things getting copied/not copied, so double check things here.
431        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    /// Encode directly to a byte vector. The resulting vector should be zeroized or overwritten
438    /// before being dropped.
439    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    /// Decrypt a lockbox's individual parts. This is only used by the `StreamInterface`
446    /// implementation.
447    fn decrypt_parts(
448        &self,
449        recipient: &LockboxRecipient,
450        parts: LockboxParts,
451    ) -> Result<Vec<u8>, CryptoError> {
452        // Verify this is the right key for this lockbox. It costs us little to do this, and saves
453        // us from potential logic errors
454        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        // Feed the lockbox's parts into the decryption algorithm
466        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        // Get the data lengths and allocate the vec
539        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 header & data
550        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        // Setup & execute encryption
557        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        // Ok, this unwrap... the only failure condition on encryption is if the content is really
563        // big. For XChaCha20Poly1305, that's 256 GiB. This library is not going to be able to
564        // handle that for many other reasons, so it is a-ok if we panic instead.
565        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(); // Make 100% certain this is zeroized at the end!
614        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)); // You didn't remove the zeroize call, right?
623        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(); // Make 100% certain this is zeroized at the end!
632        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)); // You didn't remove the zeroize call, right?
641        Some(stream_lockbox_from_parts(lockbox_vec))
642    }
643}
644
645/// An identifier for a corresponding [`StreamKey`]. It is primarily used to indicate lockboxes are
646/// meant for that particular key.
647///
648/// This is derived through a hash of the key, given a set of specific hash parameters (see
649/// [`crate::stream`]).
650///
651/// # Examples
652///
653/// A `StreamId` can be made publically visible:
654///
655/// ```
656/// # use fog_crypto::stream::*;
657///
658/// let key = StreamKey::new();
659/// let id = key.id();
660///
661/// println!("StreamId(Base58): {}", id);
662/// ```
663///
664/// It can also be used to identify a recipient of a lockbox:
665///
666/// ```
667/// # use fog_crypto::stream::*;
668/// # use fog_crypto::lockbox::*;
669/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
670/// #
671/// // We start with a known StreamKey
672/// let key = StreamKey::new();
673/// #
674/// # // Encrypt some data with the key, then turn it into a byte vector
675/// # let data = b"I am about to be enciphered, though you can't see me in here...";
676/// # let lockbox = key.encrypt_data(data.as_ref());
677/// # let mut encoded = Vec::new();
678/// # encoded.extend_from_slice(lockbox.as_bytes());
679///
680/// // ...
681/// // We get the byte vector `encoded`, which might be a lockbox
682/// // ...
683///
684/// let dec_lockbox = DataLockboxRef::from_bytes(encoded.as_ref())?;
685/// let recipient = dec_lockbox.recipient();
686/// if let LockboxRecipient::StreamId(ref id) = dec_lockbox.recipient() {
687///     // Check to see if this matches the key's StreamId
688///     if id == key.id() {
689///         let dec_data: Vec<u8> = key.decrypt_data(&dec_lockbox)?;
690///     }
691///     else {
692///         panic!("We were hoping this lockbox was for us!");
693///     }
694/// }
695/// # Ok(())
696/// # }
697/// ```
698#[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    /// Convert into a byte vector. For extending an existing byte vector, see
713    /// [`encode_vec`](Self::encode_vec).
714    pub fn as_vec(&self) -> Vec<u8> {
715        let mut v = Vec::new();
716        self.encode_vec(&mut v);
717        v
718    }
719
720    /// Convert into a base58-encoded StreamId.
721    pub fn to_base58(&self) -> String {
722        bs58::encode(&self.inner).into_string()
723    }
724
725    /// Attempt to parse a base58-encoded StreamId.
726    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    /// Value must be the same length as the StreamId was when it was encoded (no trailing bytes
746    /// allowed).
747    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    /// Display as a base58-encoded string.
779    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        // Just make sure the ID & Key aren't somehow the same
835        // I cannot imagine screwing up the code enough for this to happen, but just in case...
836        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        // Version byte corruption
878        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        // Type byte corruption
893        enc[1] |= 0x80;
894        assert!(!check_decode(&enc[..]));
895        enc[1] &= 0x07;
896        assert!(check_decrypt(&enc[..]));
897        for _ in 0..6 {
898            // First 6 increments should put it outside of expected lockbox type
899            enc[1] = (enc[1] + 1) & 0x7;
900            assert!(!check_decode(&enc[..]));
901        }
902        enc[1] = (enc[1] + 1) & 0x7; // 7th increment should still decode, but have bad recipient
903        assert!(check_decode(&enc[..]));
904        assert!(!check_decrypt(&enc[..]));
905        // Last increment should take us back to the valid value
906        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        // Identity corruption - 2 is ID version, 3 is first byte of ID
916        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        // Nonce corruption - 35 is first byte of the nonce
934        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        // Ciphertext corruption - 59 is first byte of ciphertext
947        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        // Tag corruption - corrupt the last byte
960        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        // Length extension
975        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        // Early truncation
988        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        // Corrupt the version byte
1007        content[0] = 0u8;
1008        assert!(!check_sequence(&content[..]));
1009        // Corrupt the version byte differently
1010        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        // Setup
1026        let key = StreamKey::new();
1027        let message = b"I am a test message, going undercover";
1028
1029        // Encrypt
1030        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        // Setup
1117        let key = StreamKey::new();
1118        let to_send = IdentityKey::new();
1119
1120        // Encrypt
1121        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        // Setup
1209        let key = StreamKey::new();
1210        let to_send = crate::BareIdKey::new();
1211
1212        // Encrypt
1213        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        // Setup
1264        let key = StreamKey::new();
1265        let to_send = StreamKey::new();
1266
1267        // Encrypt
1268        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        // Setup
1355        let key = StreamKey::new();
1356        let to_send = crate::BareStreamKey::new();
1357
1358        // Encrypt
1359        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        // Setup
1410        let key = StreamKey::new();
1411        let to_send = LockKey::new();
1412
1413        // Encrypt
1414        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        // Setup
1502        let key = StreamKey::new();
1503        let to_send = crate::BareLockKey::new();
1504
1505        // Encrypt
1506        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}