|
83 | 83 | //! # }
|
84 | 84 | //! ```
|
85 | 85 | //!
|
| 86 | +//! ### AES-128 CBC Streaming Cipher |
| 87 | +//! |
| 88 | +//! ```rust |
| 89 | +//! # use std::error::Error; |
| 90 | +//! # |
| 91 | +//! # fn main() -> Result<(), Box<dyn Error>> { |
| 92 | +//! use aws_lc_rs::cipher::{StreamingDecryptingKey, StreamingEncryptingKey, UnboundCipherKey, AES_128}; |
| 93 | +//! |
| 94 | +//! let original_message = "This is a secret message!".as_bytes(); |
| 95 | +//! |
| 96 | +//! let key_bytes: &[u8] = &[ |
| 97 | +//! 0xff, 0x0b, 0xe5, 0x84, 0x64, 0x0b, 0x00, 0xc8, 0x90, 0x7a, 0x4b, 0xbf, 0x82, 0x7c, 0xb6, |
| 98 | +//! 0xd1, |
| 99 | +//! ]; |
| 100 | +//! |
| 101 | +//! // Encrypt |
| 102 | +//! let mut ciphertext_buffer = vec![0u8; original_message.len() + AES_128.block_len()]; |
| 103 | +//! let ciphertext_slice = ciphertext_buffer.as_mut_slice(); |
| 104 | +//! |
| 105 | +//! let key = UnboundCipherKey::new(&AES_128, key_bytes)?; |
| 106 | +//! let mut encrypting_key = StreamingEncryptingKey::cbc_pkcs7(key)?; |
| 107 | +//! let written_slice = encrypting_key.update(original_message, ciphertext_slice)?; |
| 108 | +//! let written_len = written_slice.len(); |
| 109 | +//! let remaining_slice = &mut ciphertext_slice[written_len..]; |
| 110 | +//! let (context, written_slice) = encrypting_key.finish(remaining_slice)?; |
| 111 | +//! let ciphertext_len = written_len + written_slice.len(); |
| 112 | +//! let ciphertext = &ciphertext_slice[0..ciphertext_len]; |
| 113 | +//! |
| 114 | +//! // Decrypt |
| 115 | +//! let mut plaintext_buffer = vec![0u8; ciphertext_len + AES_128.block_len()]; |
| 116 | +//! let plaintext_slice = plaintext_buffer.as_mut_slice(); |
| 117 | +//! |
| 118 | +//! let key = UnboundCipherKey::new(&AES_128, key_bytes)?; |
| 119 | +//! let mut decrypting_key = StreamingDecryptingKey::cbc_pkcs7(key, context)?; |
| 120 | +//! let written_slice = decrypting_key.update(ciphertext, plaintext_slice)?; |
| 121 | +//! let written_len = written_slice.len(); |
| 122 | +//! let remaining_slice = &mut plaintext_slice[written_len..]; |
| 123 | +//! let written_slice = decrypting_key.finish(remaining_slice)?; |
| 124 | +//! let plaintext_len = written_len + written_slice.len(); |
| 125 | +//! let plaintext = &plaintext_slice[0..plaintext_len]; |
| 126 | +//! |
| 127 | +//! assert_eq!(original_message, plaintext); |
| 128 | +//! # |
| 129 | +//! # Ok(()) |
| 130 | +//! # } |
| 131 | +//! ``` |
| 132 | +//! |
86 | 133 | //! ## Constructing a `DecryptionContext` for decryption.
|
87 | 134 | //!
|
88 | 135 | //! ```rust
|
@@ -142,8 +189,10 @@ pub(crate) mod block;
|
142 | 189 | pub(crate) mod chacha;
|
143 | 190 | pub(crate) mod key;
|
144 | 191 | mod padded;
|
| 192 | +mod streaming; |
145 | 193 |
|
146 | 194 | pub use padded::{PaddedBlockDecryptingKey, PaddedBlockEncryptingKey};
|
| 195 | +pub use streaming::{StreamingDecryptingKey, StreamingEncryptingKey}; |
147 | 196 |
|
148 | 197 | use crate::buffer::Buffer;
|
149 | 198 | use crate::error::Unspecified;
|
@@ -280,7 +329,9 @@ impl Algorithm {
|
280 | 329 | &self.id
|
281 | 330 | }
|
282 | 331 |
|
283 |
| - const fn block_len(&self) -> usize { |
| 332 | + /// The block length of this cipher algorithm. |
| 333 | + #[must_use] |
| 334 | + pub const fn block_len(&self) -> usize { |
284 | 335 | self.block_len
|
285 | 336 | }
|
286 | 337 |
|
@@ -905,4 +956,47 @@ mod tests {
|
905 | 956 | "eca7285d19f3c20e295378460e8729",
|
906 | 957 | "b5098e5e788de6ac2f2098eb2fc6f8"
|
907 | 958 | );
|
| 959 | + |
| 960 | + #[test] |
| 961 | + fn streaming_cipher() { |
| 962 | + use crate::cipher::{ |
| 963 | + StreamingDecryptingKey, StreamingEncryptingKey, UnboundCipherKey, AES_128, |
| 964 | + }; |
| 965 | + |
| 966 | + let original_message = "This is a secret message!".as_bytes(); |
| 967 | + |
| 968 | + let key_bytes: &[u8] = &[ |
| 969 | + 0xff, 0x0b, 0xe5, 0x84, 0x64, 0x0b, 0x00, 0xc8, 0x90, 0x7a, 0x4b, 0xbf, 0x82, 0x7c, |
| 970 | + 0xb6, 0xd1, |
| 971 | + ]; |
| 972 | + |
| 973 | + // Encrypt |
| 974 | + let mut ciphertext_buffer = vec![0u8; original_message.len() + AES_128.block_len()]; |
| 975 | + let ciphertext_slice = ciphertext_buffer.as_mut_slice(); |
| 976 | + |
| 977 | + let key = UnboundCipherKey::new(&AES_128, key_bytes).unwrap(); |
| 978 | + let mut encrypting_key = StreamingEncryptingKey::cbc_pkcs7(key).unwrap(); |
| 979 | + let written_slice = encrypting_key |
| 980 | + .update(original_message, ciphertext_slice) |
| 981 | + .unwrap(); |
| 982 | + let written_len = written_slice.len(); |
| 983 | + let remaining_slice = &mut ciphertext_slice[written_len..]; |
| 984 | + let (context, written_slice) = encrypting_key.finish(remaining_slice).unwrap(); |
| 985 | + let ciphertext_len = written_len + written_slice.len(); |
| 986 | + let ciphertext = &ciphertext_slice[0..ciphertext_len]; |
| 987 | + |
| 988 | + // Decrypt |
| 989 | + let mut plaintext_buffer = vec![0u8; ciphertext_len + AES_128.block_len()]; |
| 990 | + let plaintext_slice = plaintext_buffer.as_mut_slice(); |
| 991 | + let key = UnboundCipherKey::new(&AES_128, key_bytes).unwrap(); |
| 992 | + let mut decrypting_key = StreamingDecryptingKey::cbc_pkcs7(key, context).unwrap(); |
| 993 | + let written_slice = decrypting_key.update(ciphertext, plaintext_slice).unwrap(); |
| 994 | + let written_len = written_slice.len(); |
| 995 | + let remaining_slice = &mut plaintext_slice[written_len..]; |
| 996 | + let written_slice = decrypting_key.finish(remaining_slice).unwrap(); |
| 997 | + let plaintext_len = written_len + written_slice.len(); |
| 998 | + let plaintext = &plaintext_slice[0..plaintext_len]; |
| 999 | + |
| 1000 | + assert_eq!(original_message, plaintext); |
| 1001 | + } |
908 | 1002 | }
|
0 commit comments