1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
// This file is the part of `lea-rust`. // // Author: SitD <sitd0813@gmail.com> // // This file is licensed under the Unlicense. // See LICENSE.txt for more information or you can obtain a copy at <http://unlicense.org/>. //! LEA-128/192/256-CTR implementation //! //! * Examples //! //! Encryption //! ``` //! use lea::ctr::Lea256Ctr; //! use lea::stream_cipher::{NewStreamCipher, StreamCipher}; //! use lea::generic_array::arr; //! use lea::generic_array::arr_impl; //! //! let key = arr![u8; 0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2, 0xE1, 0xF0, //! 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F]; //! let counter = arr![u8; 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]; //! let mut lea256ctr = Lea256Ctr::new(&key, &counter); //! //! let mut data = arr![u8; 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, //! 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, //! 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F]; //! //! lea256ctr.encrypt(&mut data); //! //! let cipher = arr![u8; 0x15, 0x39, 0xF7, 0xA2, 0x1C, 0x0F, 0x16, 0x07, 0x6D, 0x90, 0xFB, 0xEB, 0x03, 0x97, 0xD4, 0x40, //! 0x2D, 0xFD, 0x4E, 0xB0, 0x44, 0x0B, 0x28, 0x3D, 0xE7, 0xE3, 0x0C, 0x36, 0x0D, 0x71, 0xF1, 0x47, //! 0x0E, 0x8B, 0xAF, 0xD2, 0x88, 0x3B, 0xA8, 0x08, 0x8D, 0x0C, 0x5D, 0xA7, 0xA9, 0x14, 0xAE, 0x90]; //! //! assert_eq!(data, cipher); //! ``` //! //! Decryption //! ``` //! use lea::ctr::Lea256Ctr; //! use lea::stream_cipher::{NewStreamCipher, StreamCipher}; //! use lea::generic_array::arr; //! use lea::generic_array::arr_impl; //! //! let key = arr![u8; 0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2, 0xE1, 0xF0, //! 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, 0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F]; //! let counter = arr![u8; 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]; //! let mut lea256ctr = Lea256Ctr::new(&key, &counter); //! //! let mut data = arr![u8; 0x15, 0x39, 0xF7, 0xA2, 0x1C, 0x0F, 0x16, 0x07, 0x6D, 0x90, 0xFB, 0xEB, 0x03, 0x97, 0xD4, 0x40, //! 0x2D, 0xFD, 0x4E, 0xB0, 0x44, 0x0B, 0x28, 0x3D, 0xE7, 0xE3, 0x0C, 0x36, 0x0D, 0x71, 0xF1, 0x47, //! 0x0E, 0x8B, 0xAF, 0xD2, 0x88, 0x3B, 0xA8, 0x08, 0x8D, 0x0C, 0x5D, 0xA7, 0xA9, 0x14, 0xAE, 0x90]; //! //! lea256ctr.decrypt(&mut data); //! //! let plain = arr![u8; 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, //! 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, //! 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F]; //! //! assert_eq!(data, plain); //! ``` use cfg_if::cfg_if; use crate::{Lea128, Lea192, Lea256}; use crate::block_cipher_trait::BlockCipher; use crate::generic_array::ArrayLength; use crate::generic_array::GenericArray; use crate::generic_array::typenum::{U16, U24, U32}; use crate::stream_cipher::{NewStreamCipher, StreamCipher}; macro_rules! generate_lea_ctr { ($name:ident, $cipher:ident, $key_size:ty) => { pub struct $name { cipher: $cipher, nonce: GenericArray<u8, U16>, } impl NewStreamCipher for $name { type KeySize = $key_size; type NonceSize = U16; fn new(key: &GenericArray<u8, Self::KeySize>, nonce: &GenericArray<u8, Self::NonceSize>) -> Self { let cipher = $cipher::new(&key); let nonce = *nonce; Self { cipher, nonce } } } impl StreamCipher for $name { fn encrypt(&mut self, data: &mut [u8]) { encrypt(&self.cipher, &self.nonce, data); } fn decrypt(&mut self, data: &mut [u8]) { encrypt(&self.cipher, &self.nonce, data); } } }; } generate_lea_ctr!(Lea128Ctr, Lea128, U16); generate_lea_ctr!(Lea192Ctr, Lea192, U24); generate_lea_ctr!(Lea256Ctr, Lea256, U32); fn encrypt<C: BlockCipher>(cipher: &C, nonce: &GenericArray<u8, C::BlockSize>, data: &mut [u8]) { let mut counter = nonce.clone(); for data in data.chunks_mut(16) { let mut block = counter.clone(); cipher.encrypt_block(&mut block); for i in 0..(data.len()) { data[i] ^= block[i]; } increment_counter(&mut counter); } } fn increment_counter<L: ArrayLength<u8>>(counter: &mut GenericArray<u8, L>) { cfg_if! { if #[cfg(target_endian = "big")] { for n in counter.iter_mut() { *n += 1; if *n != 0 { break; } } } else if #[cfg(target_endian = "little")] { #[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_ptr_alignment))] unsafe { *(counter.as_mut_ptr() as *mut u128) += 1 }; } } }