dcrypt_algorithms/stream/
mod.rs

1//! Stream cipher implementations
2//!
3//! This module provides implementations of stream ciphers, which are symmetric
4//! key ciphers that encrypt plaintext digits one at a time with a pseudorandom
5//! keystream.
6//!
7//! # Available Stream Ciphers
8//!
9//! - ChaCha20: A high-speed stream cipher designed by Daniel J. Bernstein
10//!
11//! # Security Considerations
12//!
13//! Stream ciphers require unique nonces for each encryption operation with the
14//! same key. Reusing a nonce with the same key completely breaks the security
15//! of the cipher.
16
17#![cfg_attr(not(feature = "std"), no_std)]
18
19/// ChaCha family of stream cipher implementations
20pub mod chacha;
21
22// Re-export commonly used types
23pub use chacha::chacha20::{ChaCha20, CHACHA20_BLOCK_SIZE, CHACHA20_KEY_SIZE, CHACHA20_NONCE_SIZE};
24
25use crate::error::{Error, Result};
26
27/// Common trait for stream cipher implementations
28pub trait StreamCipher {
29    /// The key size in bytes
30    const KEY_SIZE: usize;
31
32    /// The nonce size in bytes
33    const NONCE_SIZE: usize;
34
35    /// The internal block size in bytes (if applicable)
36    const BLOCK_SIZE: usize;
37
38    /// Process data in place (encrypts for encryption, decrypts for decryption)
39    fn process(&mut self, data: &mut [u8]) -> Result<()>;
40
41    /// Encrypt data in place
42    fn encrypt(&mut self, data: &mut [u8]) -> Result<()> {
43        self.process(data)
44    }
45
46    /// Decrypt data in place
47    fn decrypt(&mut self, data: &mut [u8]) -> Result<()> {
48        self.process(data)
49    }
50
51    /// Generate keystream directly into an output buffer
52    fn keystream(&mut self, output: &mut [u8]) -> Result<()>;
53
54    /// Reset the cipher to its initial state
55    fn reset(&mut self) -> Result<()>;
56
57    /// Seek to a specific position in the keystream (if supported)
58    fn seek(&mut self, position: u64) -> Result<()>;
59}
60
61// Implement StreamCipher for ChaCha20
62impl StreamCipher for ChaCha20 {
63    const KEY_SIZE: usize = CHACHA20_KEY_SIZE;
64    const NONCE_SIZE: usize = CHACHA20_NONCE_SIZE;
65    const BLOCK_SIZE: usize = CHACHA20_BLOCK_SIZE;
66
67    fn process(&mut self, data: &mut [u8]) -> Result<()> {
68        self.process(data);
69        Ok(())
70    }
71
72    fn keystream(&mut self, output: &mut [u8]) -> Result<()> {
73        self.keystream(output);
74        Ok(())
75    }
76
77    fn reset(&mut self) -> Result<()> {
78        self.reset();
79        Ok(())
80    }
81
82    fn seek(&mut self, position: u64) -> Result<()> {
83        if position > u32::MAX as u64 {
84            // Use the new Error::param helper
85            return Err(Error::param(
86                "position",
87                "ChaCha20 seek position must fit in u32",
88            ));
89        }
90        self.seek(position as u32);
91        Ok(())
92    }
93}