# `ExWapp.AppState.Crypto`
[🔗](https://github.com/elchemista/ex_wapp/blob/v0.1.5/lib/ex_wapp/appstate/crypto.ex#L2)

Cryptographic primitives for WhatsApp App State Sync.

Implements key expansion, AES-256-CBC encrypt/decrypt, and MAC computation
matching whatsmeow's `appstate/keys.go` and `appstate/hash.go`.

# `expanded_keys`

```elixir
@type expanded_keys() :: %{
  index: binary(),
  value_encryption: binary(),
  value_mac: binary(),
  snapshot_mac: binary(),
  patch_mac: binary()
}
```

# `compute_content_mac`

```elixir
@spec compute_content_mac(non_neg_integer(), binary(), binary(), binary()) :: binary()
```

Compute content/value MAC: first 32 bytes of HMAC-SHA512.

Data = operation_byte || key_id || encrypted_content || big_endian_u64(len(key_id)+1)

Operation byte = SyncdOperation value + 1 (SET=0 → byte 1, REMOVE=1 → byte 2).

Matches whatsmeow `generateContentMAC()` in `hash.go:94-98`.

# `compute_index_mac`

```elixir
@spec compute_index_mac(binary(), binary()) :: binary()
```

Compute index MAC: HMAC-SHA256(index_key, index_json).

Matches whatsmeow `concatAndHMAC(sha256.New, keys.Index, indexBytes)` in `encode.go:300`.

# `compute_patch_mac`

```elixir
@spec compute_patch_mac(binary(), [binary()], non_neg_integer(), binary(), binary()) ::
  binary()
```

Compute patch MAC: HMAC-SHA256(patch_mac_key, snapshot_mac || value_macs... || version_u64 || collection_name).

Matches whatsmeow `generatePatchMAC()` in `hash.go:82-92`.

# `compute_snapshot_mac`

```elixir
@spec compute_snapshot_mac(binary(), non_neg_integer(), binary(), binary()) ::
  binary()
```

Compute snapshot MAC: HMAC-SHA256(snapshot_mac_key, hash_state || version_u64 || collection_name).

Matches whatsmeow `HashState.generateSnapshotMAC()` in `hash.go:78-80`.

# `decrypt_cbc`

```elixir
@spec decrypt_cbc(binary(), binary(), binary()) :: {:ok, binary()} | {:error, term()}
```

Decrypt AES-256-CBC ciphertext and remove PKCS7 padding.

Matches whatsmeow `cbcutil.Decrypt()`.

# `encrypt_cbc`

```elixir
@spec encrypt_cbc(binary(), binary(), binary() | nil) :: {binary(), binary()}
```

Encrypt plaintext with AES-256-CBC + PKCS7 padding.

When `iv` is nil, generates a random 16-byte IV.
Returns `{iv, ciphertext}`.

Matches whatsmeow `cbcutil.Encrypt()`.

# `expand_keys`

```elixir
@spec expand_keys(binary()) :: expanded_keys()
```

Expand a 32-byte app state key into 5 sub-keys (160 bytes total) via HKDF-SHA256.

Matches whatsmeow `expandAppStateKeys()` in `appstate/keys.go:81-84`.

---

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