xts

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: BSD-3-Clause Imports: 6 Imported by: 2

README

go-encryptions/xts

go-encryptions/xts

ci Go Reference

Pure-Go XTS-AES tweakable block-cipher mode (IEEE P1619/D16, NIST SP 800-38E), the sector-level disk-encryption mode used by LUKS, APFS FileVault 2, BitLocker and dm-crypt.

It is a drop-in replacement for golang.org/x/crypto/xts: the Cipher type exposes the same NewCipher / Encrypt / Decrypt API and produces byte-identical ciphertext. The difference is performance. x/crypto/xts drives the block cipher one 16-byte block at a time through the cipher.Block interface, which collapses a hardware AES engine to a fraction of its throughput. This package instead ships a fused AES-XTS kernel that pipelines four AES blocks at a time and folds the tweak XOR into the round pipeline:

  • amd64 (AES-NI) and arm64 (ARMv8 AES + NEON) run the AESENC / AESE·AESMC pipeline directly in Plan 9 assembly, reaching multi-GB/s per core.
  • riscv64, loong64, ppc64le, s390x transparently fall back to the same per-block algorithm as x/crypto/xts, so behaviour is identical everywhere — only the speed differs.

Built for the go-encryptions family; the primary consumers are the full-disk-encryption backends go-fde/luks and go-fde/apfs.

Install

go get github.com/go-encryptions/xts

Usage

import (
	"crypto/aes"

	"github.com/go-encryptions/xts"
)

// key is the concatenation of two AES keys (32, 48 or 64 bytes total).
c, err := xts.NewCipher(aes.NewCipher, key)
if err != nil { /* ... */ }

c.Encrypt(ciphertext, plaintext, sectorNum) // one 512/4096-byte sector
c.Decrypt(plaintext, ciphertext, sectorNum)

Encrypt and Decrypt operate on a whole disk sector at a time; sectorNum is the tweak (the sector index). Buffers must be a whole number of 16-byte blocks and at least one block long, matching the x/crypto/xts contract.

Guarantees

  • Byte-identical output to golang.org/x/crypto/xts on every architecture, verified in CI against x/crypto as a reference oracle.
  • CGO=0, no unsafe in the API surface, no external deps beyond golang.org/x/sys/cpu (AES-NI feature detection) and golang.org/x/crypto (test-only cross-check).
  • All six 64-bit Go targets — amd64, arm64, riscv64, loong64, ppc64le and big-endian s390x — are built and tested in CI (native + QEMU), with a 100%-of-statements coverage gate.

License

BSD-3-Clause © the go-encryptions/xts authors.

Documentation

Overview

Package xts implements the XTS-AES tweakable block-cipher mode (IEEE P1619/D16, NIST SP 800-38E) used for full-disk encryption.

It is a drop-in replacement for golang.org/x/crypto/xts: the Cipher type exposes the same NewCipher / Encrypt / Decrypt API and produces byte-identical ciphertext. The difference is performance. x/crypto/xts drives the underlying block cipher one 16-byte block at a time through the cipher.Block interface and advances the XTS tweak with a scalar GF(2^128) multiply per block; on a CPU with hardware AES this collapses a ~10 GB/s AES engine to ~600 MB/s because the per-block interface dispatch defeats the pipelined multi-block AES path.

This package instead ships a fused AES-XTS kernel that pipelines four AES blocks at a time and folds the tweak XOR into the round pipeline. On arm64 (ARMv8 AES + NEON) and amd64 (AES-NI) the kernel runs the AESE/AESMC (resp. AESENC) pipeline directly, reaching multi-GB/s per core. On the remaining architectures (riscv64, loong64, ppc64le, s390x) it transparently falls back to the same per-block algorithm as x/crypto/xts, so behaviour is identical everywhere; only the speed differs.

XTS provides confidentiality but no authentication, and does not implement ciphertext stealing, so each sector must be a multiple of 16 bytes. It is intended for disk-sector encryption only.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cipher

type Cipher struct {
	// contains filtered or unexported fields
}

Cipher is an expanded XTS key. It is safe for concurrent use.

func NewCipher

func NewCipher(cipherFunc func([]byte) (cipher.Block, error), key []byte) (*Cipher, error)

NewCipher creates a Cipher from a function that builds the underlying block cipher (which must have a 16-byte block size) and a key that is twice the underlying cipher's key length. For AES this is a 32-byte key (AES-128-XTS) or a 64-byte key (AES-256-XTS).

func (*Cipher) Decrypt

func (c *Cipher) Decrypt(plaintext, ciphertext []byte, sectorNum uint64)

Decrypt decrypts a sector of ciphertext into plaintext using the given sector number as the XTS tweak. The same overlap and length rules as Encrypt apply.

func (*Cipher) Encrypt

func (c *Cipher) Encrypt(ciphertext, plaintext []byte, sectorNum uint64)

Encrypt encrypts a sector of plaintext into ciphertext using the given sector number as the XTS tweak. ciphertext and plaintext must overlap entirely or not at all, and len(plaintext) must be a non-zero multiple of 16 bytes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL