# `SpeckEx.CTR`
[🔗](https://github.com/juulSme/SpeckEx/blob/v0.2.0/lib/speck_ex/ctr.ex#L1)

Counter (CTR) mode encryption using the Speck block cipher.

This module provides stream cipher encryption using Speck in CTR mode,
allowing encryption of data of arbitrary length. CTR mode turns a block
cipher into a stream cipher by encrypting a counter value.

> #### Here be dragons {: .warning}
>
> This is a "no guardrails" implementation module, where nonce generation is your own responsibility. Use the main `SpeckEx` module unless you know what you are doing. Be sure to read the `m:SpeckEx#module-security-guidelines` security guidelines.

## Supported Variants

Only Speck variants with 32, 64 and 128-bit block sizes are supported because of limitations of the backing Rust "ctr" crate:

- `:speck32_64` - 32-bit block, 64-bit key (4-byte block, 8-byte key)
- `:speck64_96` - 64-bit block, 96-bit key (8-byte block, 12-byte key)
- `:speck64_128` - 64-bit block, 128-bit key (8-byte block, 16-byte key)
- `:speck128_128` - 128-bit block, 128-bit key (16-byte block, 16-byte key)
- `:speck128_192` - 128-bit block, 192-bit key (16-byte block, 24-byte key)
- `:speck128_256` - 128-bit block, 256-bit key (16-byte block, 32-byte key, default)

## Usage

    # Generate a random key (32 bytes for default speck128_256)
    iex> key = :crypto.strong_rand_bytes(32)
    iex> nonce = :crypto.strong_rand_bytes(16)
    iex> ciphertext = SpeckEx.CTR.crypt("Secret message", key, nonce)
    iex> SpeckEx.CTR.crypt(ciphertext, key, nonce)
    "Secret message"

# `variant`

```elixir
@type variant() ::
  :speck32_64
  | :speck64_96
  | :speck64_128
  | :speck128_128
  | :speck128_192
  | :speck128_256
```

Speck variants with 32, 64 and 128-bit block sizes, supported by CTR and AEAD modes.

# `crypt`

```elixir
@spec crypt(binary(), binary(), binary(), variant()) :: binary()
```

En/decrypt using CTR mode.

## Parameters

- `data` - The data to en/decrypt (binary, any length)
- `key` - The encryption key (size depends on variant)
- `nonce` - The initialization vector (size depends on variant, MUST be unique per key)
- `variant` - The Speck variant to use (default: `:speck128_256`)

## Returns

The encrypted ciphertext or decrypted plaintext as a binary (same length as data).

## Examples

    iex> key = :crypto.strong_rand_bytes(32)
    iex> nonce = :crypto.strong_rand_bytes(16)
    iex> ciphertext = SpeckEx.CTR.crypt("Hello, World!", key, nonce)
    iex> is_binary(ciphertext) and byte_size(ciphertext) == byte_size("Hello, World!")
    true

---

*Consult [api-reference.md](api-reference.md) for complete listing*
