Symmetric
Default: ChaCha20. It’s ARX (add/rotate/xor) with no lookup tables so it’s immune to cache-timing by construction. It’s also faster than software AES on CPU. Use AES only where a spec requires it. Prefer has_aes_ni() when you do since the software S-box path is table-based and not cache-timing safe.
thistle.ChaCha20
def __init__(out self, key_bytes: SIMD[DType.uint8, 32],
nonce_bytes: SIMD[DType.uint8, 12], counter: UInt32 = 1)
def encrypt_inplace[origin: Origin[mut=True]](mut self, mut data: Span[mut=True, UInt8, origin]) raises
def encrypt_into[origin: Origin[mut=True]](mut self, plaintext: Span[UInt8, ...], mut ciphertext: Span[mut=True, UInt8, origin]) raises
def decrypt_into[origin: Origin[mut=True]](mut self, ciphertext: Span[UInt8, ...], mut plaintext: Span[mut=True, UInt8, origin]) raises
var enc = ChaCha20(key, nonce)
enc.encrypt_inplace(buffer_span) # buffer_span is Span[mut=True, UInt8]
var dec = ChaCha20(key, nonce) # same key + nonce
dec.encrypt_inplace(buffer_span) # decrypt == encrypt
- Note: never reuse a (key, nonce) pair across two different plaintexts.
- Note: raises past ~256 GiB encrypted under one nonce instead of reusing keystream.
- Note:
encrypt_intoraises ifciphertextis shorter thanplaintext. - Note: no authentication. Pair with
hmac_sha256over the ciphertext for tamper detection.
thistle.CamelliaCipher
def __init__(out self, key: Span[UInt8, ...]) raises # 16, 24, or 32 bytes
def encrypt(self, block: SIMD[DType.uint8, 16]) -> SIMD[DType.uint8, 16]
def decrypt(self, block: SIMD[DType.uint8, 16]) -> SIMD[DType.uint8, 16]
def wipe(mut self)
Span[UInt8, ...] overloads of encrypt/decrypt also exist (raise if not exactly 16 bytes).
var cipher = CamelliaCipher(key)
var ct = cipher.encrypt(block)
var pt = cipher.decrypt(ct)
cipher.wipe()
- Note: constructor raises on any key length other than 16/24/32.
- Note: constant-time. S-boxes run on AES round instructions (16-way byte-sliced, ~1.2 GB/s bulk on Apple M-series) when hardware AES is present, bitsliced otherwise. No secret-indexed table lookups.
AES
thistle.aes is software, bitsliced and constant-time. thistle.aes_ni is hardware for x86 and ARM. Check has_aes_ni() first. thistle.aes_gpu has aes_gpu_kernel_ecb/ctr/gcm for bulk data.
thistle.KCipher2
ISO/IEC 18033-4 stream cipher. Fixed-width SIMD key/IV constructor. No reason to use it unless a spec requires it.
Constant-time: the T-table lookups (S-box and GF(2^32) multiply tables) are gone. sub_k2 is AES SubBytes + MixColumns, so it runs on AES round instructions (~1.8 GB/s keystream on Apple M-series) with a bitsliced fallback; the alpha multiplies are masked XORs of 8 basis constants.