7个版本 (4个重大更改)
0.5.1 | 2022年10月31日 |
---|---|
0.5.0 | 2022年2月25日 |
0.4.1 | 2021年9月23日 |
0.4.0 | 2021年5月1日 |
0.1.0 | 2020年4月30日 |
#1242 in 加密学
38,580 个月下载量
用于 3 个crate(2个直接使用)
20KB
183 行
xts-mode
XTS分组模式 在Rust中的实现。
目前这个实现仅支持128位(16字节)块大小的加密算法(与密钥大小不同)。请注意,AES-256使用128位块,因此与这个crate兼容。如果您需要其他加密算法的块大小,请提出一个issue。
示例
同时加密和解密多个扇区
use aes::{Aes128, cipher::KeyInit, cipher::generic_array::GenericArray};
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(GenericArray::from_slice(&key[..16]));
let cipher_2 = Aes128::new(GenericArray::from_slice(&key[16..]));
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[..]);
AES-256也可以
use aes::{Aes256, cipher::KeyInit, cipher::generic_array::GenericArray};
use xts_mode::{Xts128, get_tweak_default};
// Load the encryption key
let key = [1; 64];
let plaintext = [5; 0x400];
// Load the data to be encrypted
let mut buffer = plaintext.to_owned();
let cipher_1 = Aes256::new(GenericArray::from_slice(&key[..32]));
let cipher_2 = Aes256::new(GenericArray::from_slice(&key[32..]));
let xts = Xts128::<Aes256>::new(cipher_1, cipher_2);
let sector_size = 0x200;
let first_sector_index = 0;
xts.encrypt_area(&mut buffer, sector_size, first_sector_index, get_tweak_default);
xts.decrypt_area(&mut buffer, sector_size, first_sector_index, get_tweak_default);
assert_eq!(&buffer[..], &plaintext[..]);
加密和解密单个扇区
use aes::{Aes128, cipher::KeyInit, cipher::generic_array::GenericArray};
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(GenericArray::from_slice(&key[..16]));
let cipher_2 = Aes128::new(GenericArray::from_slice(&key[16..]));
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[..]);
解密NCA(任天堂内容存档)头部
use aes::{Aes128, cipher::KeyInit, cipher::generic_array::GenericArray};
use xts_mode::{Xts128, get_tweak_default};
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(GenericArray::from_slice(&header_key[..0x10]));
let cipher_2 = Aes128::new(GenericArray::from_slice(&header_key[0x10..]));
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);
依赖项
~0.4–1MB
~21K SLoC