XTS block mode implementation in rust. Currently only 128-bit (16-byte) algorithms are supported, if you require other sizes, please open an issue.
For better AES performance, it is recommended to use the aes
crate and enable the aes
feature in
the compiler (see reference
and aesni).
Encrypting and decrypting multiple sectors at a time: ```rust use aes::Aes128; use aes::blockciphertrait::BlockCipher; use xtsmode::{Xts128, gettweak_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 cipher1 = Aes128::newvarkey(&key[..16]).unwrap(); let cipher2 = Aes128::newvarkey(&key[16..]).unwrap();
let xts = Xts128::
let sectorsize = 0x200; let firstsector_index = 0;
// Encrypt data in the buffer xts.encryptarea(&mut buffer, sectorsize, firstsectorindex, gettweakdefault);
// Decrypt data in the buffer xts.decryptarea(&mut buffer, sectorsize, firstsectorindex, gettweakdefault);
assert_eq!(&buffer[..], &plaintext[..]); ```
Encrypting and decrypting a single sector: ```rust use aes::Aes128; use aes::blockciphertrait::BlockCipher; use xtsmode::{Xts128, gettweak_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 cipher1 = Aes128::newvarkey(&key[..16]).unwrap(); let cipher2 = Aes128::newvarkey(&key[16..]).unwrap();
let xts = Xts128::
let tweak = gettweakdefault(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: ```rust use aes::Aes128; use aes::blockciphertrait::BlockCipher; use xts_mode::Xts128;
pub fn getnintendotweak(sectorindex: u128) -> [u8; 0x10] { sectorindex.tobebytes() }
// Load the header key let header_key = &[0; 0x20];
// Read into buffer header to be decrypted let mut buffer = vec![0; 0xC00];
let cipher1 = Aes128::newvarkey(&headerkey[..0x10]).unwrap(); let cipher2 = Aes128::newvarkey(&headerkey[0x10..]).unwrap();
let mut xts = Xts128::new(cipher1, cipher2);
// Decrypt the first 0x400 bytes of the header in 0x200 sections xts.decryptarea(&mut buffer[0..0x400], 0x200, 0, getnintendo_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.decryptarea(&mut buffer[0x400..0xC00], 0x200, 2, getnintendo_tweak); ```