silk.crypto.aes_xts.

Encrypt storage sectors with AES-XTS (IEEE 1619, NIST SP 800-38E).

When to use#

Use AesXts where a disk or file format names XTS, or for Node's aes-128-xts and aes-256-xts. XTS is made for storage: it does not detect changes, and it does not hide when a sector is written again with the same data. Use silk.crypto.aes_gcm for messages.

Details#

The key is two AES keys side by side: 32 bytes for AES-128-XTS or 64 bytes for AES-256-XTS. The 16-byte tweak names the data unit, usually the sector number. Each call encrypts or decrypts one whole data unit of at least 16 bytes. A length that is not a multiple of 16 uses ciphertext stealing, so the ciphertext has the same length as the plaintext. Nothing allocates.

Errors#

The functions return an AesXtsError. Every check comes before the first write, and on an error the output does not change.

Gotchas#

Encryption rejects a key whose two halves are equal, as OpenSSL does. A data unit is at most 2^20 blocks, OpenSSL's limit. Each call is one data unit: splitting a sector across calls gives a different result.

Examples#

Encrypt and decrypt a sector#

silk
import silk.crypto.aes_xts { AesXts, AesXtsError }
import silk.core.result { Result }

pub fn main() -> i32 {
  let mut key: [u8; 32] = [0; 32]
  key[16] = 1
  let tweak: [u8; 16] = [0; 16]
  let sector: [u8; 20] = [7; 20]
  let mut ciphertext: [u8; 20] = [0; 20]
  if let Result.Failure { error: _ } = AesXts.encrypt(&key, &tweak, &sector, &mut ciphertext) {
    return 1
  }
  let mut plaintext: [u8; 20] = [0; 20]
  if let Result.Failure { error: _ } = AesXts.decrypt(&key, &tweak, &ciphertext, &mut plaintext) {
    return 1
  }
  if plaintext[0] != 7 || plaintext[19] != 7 {
    return 1
  }
  return 0
}

Import as AesXts with import silk.crypto.aes_xts { AesXts }.

Public declarations: 2.

AesXtsError#

silk
pub enum AesXtsError

The reason that AesXts.encrypt or AesXts.decrypt rejected a call. The output does not change.

InvalidKeyLength#

silk
InvalidKeyLength

The key is not 32 or 64 bytes.

DuplicateKeyHalves#

silk
DuplicateKeyHalves

The two halves of the key are equal, which XTS encryption does not allow.

InvalidIvLength#

silk
InvalidIvLength

The tweak is not 16 bytes.

InvalidInputLength#

silk
InvalidInputLength

The data unit is shorter than 16 bytes or longer than 2^20 blocks.

OutputTooSmall#

silk
OutputTooSmall

The output is shorter than the input.

Implementation Debug for AesXtsError#

silk
impl Debug for AesXtsError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut Writer

Writes the name of the variant, such as InvalidKeyLength.

AesXts#

silk
pub struct AesXts

Functions that encrypt and decrypt one data unit with AES-XTS (IEEE 1619).

Details#

The key is 32 bytes (AES-128-XTS) or 64 bytes (AES-256-XTS): the first half encrypts the data and the second half encrypts the tweak. Each call handles one data unit of 16 bytes to 2^20 blocks, with ciphertext stealing for a partial last block. Nothing allocates.

Gotchas#

XTS does not detect changes to the ciphertext. Encryption rejects a key whose halves are equal.

Implementation AesXts#

silk
impl AesXts

Associated function encrypt#

silk
pub fn encrypt(key: &[u8], tweak: &[u8], plaintext: &[u8], ciphertext: &mut [u8]) -> Result<(), AesXtsError>

Encrypts the data unit plaintext with key and tweak into the first plaintext.length bytes of ciphertext.

Errors#

  • InvalidKeyLength if key is not 32 or 64 bytes.

  • DuplicateKeyHalves if the two halves of key are equal.

  • InvalidIvLength if tweak is not 16 bytes.

  • InvalidInputLength if plaintext is shorter than 16 bytes or longer than 2^20 blocks.

  • OutputTooSmall if ciphertext is shorter than plaintext.

Associated function decrypt#

silk
pub fn decrypt(key: &[u8], tweak: &[u8], ciphertext: &[u8], plaintext: &mut [u8]) -> Result<(), AesXtsError>

Decrypts the data unit ciphertext with key and tweak into the first ciphertext.length bytes of plaintext.

Errors#

  • InvalidKeyLength if key is not 32 or 64 bytes.

  • InvalidIvLength if tweak is not 16 bytes.

  • InvalidInputLength if ciphertext is shorter than 16 bytes or longer than 2^20 blocks.

  • OutputTooSmall if plaintext is shorter than ciphertext.

Category: Cryptography.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.

View the source of this page