Crate xts_mode[−][src]
XTS block mode implementation in rust. Currently only 128-bit (16-byte) algorithms are supported, if you require other sizes, please open an issue. Note that AES-256 uses 128-bit blocks, so it should work as is.
Examples:
Encrypting and decrypting multiple sectors at a time:
use aes::Aes128; use aes::NewBlockCipher; use xts_mode::{Xts128, get_tweak_default}; // Load the encryption key let key = [1; 32]; let plaintext = [5; 0x400]; // Load the data to be encrypted let mut buffer = plaintext.to_owned(); let cipher_1 = Aes128::new_from_slice(&key[..16]).unwrap(); let cipher_2 = Aes128::new_from_slice(&key[16..]).unwrap(); let xts = Xts128::<Aes128>::new(cipher_1, cipher_2); let sector_size = 0x200; let first_sector_index = 0; // Encrypt data in the buffer xts.encrypt_area(&mut buffer, sector_size, first_sector_index, get_tweak_default); // Decrypt data in the buffer xts.decrypt_area(&mut buffer, sector_size, first_sector_index, get_tweak_default); assert_eq!(&buffer[..], &plaintext[..]);
Encrypting and decrypting a single sector:
use aes::Aes128; use aes::NewBlockCipher; use xts_mode::{Xts128, get_tweak_default}; // Load the encryption key let key = [1; 32]; let plaintext = [5; 0x200]; // Load the data to be encrypted let mut buffer = plaintext.to_owned(); let cipher_1 = Aes128::new_from_slice(&key[..16]).unwrap(); let cipher_2 = Aes128::new_from_slice(&key[16..]).unwrap(); let xts = Xts128::<Aes128>::new(cipher_1, cipher_2); let tweak = get_tweak_default(0); // 0 is the sector index // Encrypt data in the buffer xts.encrypt_sector(&mut buffer, tweak); // Decrypt data in the buffer xts.decrypt_sector(&mut buffer, tweak); assert_eq!(&buffer[..], &plaintext[..]);
Decrypting a NCA (nintendo content archive) header:
use aes::Aes128; use aes::NewBlockCipher; use xts_mode::Xts128; pub fn get_nintendo_tweak(sector_index: u128) -> [u8; 0x10] { sector_index.to_be_bytes() } // Load the header key let header_key = &[0; 0x20]; // Read into buffer header to be decrypted let mut buffer = vec![0; 0xC00]; let cipher_1 = Aes128::new_from_slice(&header_key[..0x10]).unwrap(); let cipher_2 = Aes128::new_from_slice(&header_key[0x10..]).unwrap(); let mut xts = Xts128::new(cipher_1, cipher_2); // Decrypt the first 0x400 bytes of the header in 0x200 sections xts.decrypt_area(&mut buffer[0..0x400], 0x200, 0, get_nintendo_tweak); let magic = &buffer[0x200..0x204]; assert_eq!(magic, b"NCA3"); // In older NCA versions the section index used in header encryption was different // Decrypt the rest of the header xts.decrypt_area(&mut buffer[0x400..0xC00], 0x200, 2, get_nintendo_tweak);
Structs
| Xts128 | Xts128 block cipher. Does not implement implement BlockMode due to XTS differences detailed here. |
Functions
| get_tweak_default | This is the default way to get the tweak, which just consists of separating the sector_index
in an array of 16 bytes with little endian. May be called to get the tweak for every sector
or passed directly to |