# Algorithm registry

This registry defines stable algorithm IDs and the textual values introduced in [ADR 005](adr/005-wire-format.md). IDs belong to one family; signature and public-key IDs are separate. An ID or text name is never reassigned. Zero is unspecified and cannot select an algorithm. Registration permits representation; execution also requires support for the requested scope.

All current entries are `active` with no deadline. `—` in `deprecated_after` means unset (`None`). Protobuf persistence, repository policy checks and capability advertisement are implemented; the [architecture](architecture.md#persistence-and-public-identities) describes the current boundary and the [implementation record](IMPLEMENTATION_AUDIT.md) records verification.

## Hash

| ID | Algorithm | Text ID | Value bytes | Status | deprecated_after (UTC) | Current scope |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | BLAKE3 | `b3` | 32 | active | — | Content hashes and protocol identities |
| 2 | SHA-256 | `sha256` | 32 | active | — | Typed digest values; content and protocol identities reject this algorithm |
| 3 | SHA-512 | `sha512` | 64 | active | — | Typed digest values; content and protocol identities reject this algorithm |

## AEAD

| ID | Algorithm | Text ID | Nonce bytes | Tag bytes | Status | deprecated_after (UTC) | Current scope |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | XChaCha20-Poly1305 | `xchacha20poly1305` | 24 | 16 | active | — | Content, local protection, index segments/snapshots and key wrapping |
| 2 | AES-256-GCM | `aes256gcm` | 12 | 16 | active | — | Content |
| 3 | ChaCha20-Poly1305 | `chacha20poly1305` | 12 | 16 | active | — | Content |

## Signature

| ID | Algorithm | Text ID | Value bytes | Status | deprecated_after (UTC) | Current scope |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | Ed25519 | `ed25519` | 64 | active | — | Device and recovery-authority signatures |

## Public key

| ID | Algorithm | Text ID | Value bytes | Status | deprecated_after (UTC) | Current scope |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | Ed25519 | `ed25519` | 32 | active | — | Device identity and signature verification |
| 2 | X25519 | `x25519` | 32 | active | — | Sealed-box recipients and ephemeral keys |

## KDF

| ID | Algorithm | Text ID | Status | deprecated_after (UTC) | Current scope |
| --- | --- | --- | --- | --- | --- |
| 1 | Argon2id | `argon2id` | active | — | Password-derived wrapping keys; salt, wire `memory_cost_bytes`, iterations, parallelism, output length and version are explicit |

The Rust `VaultConfig.argon2_m_cost` remains in KiB; the protobuf codec converts it to/from `memory_cost_bytes` with strict alignment and bounds. Existing domain-separated key-derivation labels retain their current meanings.

## Chunking

| ID | Algorithm | Text ID | Status | deprecated_after (UTC) | Current scope |
| --- | --- | --- | --- | --- | --- |
| 1 | FastCDC 2020 | `fastcdc-2020` | active | — | Content writer with min/average/max size parameters |
| 2 | Fixed boundaries | `fixed` | active | — | Content writer with a chunk-size parameter |

These IDs are assigned to the existing writer strategies. Readers follow stored unit boundaries.

## Canonical text and validation

`Digest`, `Signature` and `PublicKey` render as `<text-id>.<base58-value>`. The algorithm prefix is exactly the lower-case registered name; the value is case-sensitive Bitcoin base58 using `123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`. Encode raw bytes without a checksum, preserving each leading zero byte as a leading `1`. Decoding must satisfy the exact byte length in its family and reproduce the same text when encoded again. Reject whitespace, aliases, unknown prefixes, empty values, invalid characters and noncanonical encodings. AEAD, KDF and chunking text IDs identify algorithms; they do not encode a value by themselves.

DeviceId and public peer NodeId use `ed25519.`; VersionId, RetirementId and KeyEpoch use `b3.`. FileId, SubtreeId, StoreId and VaultId are exact 16-byte random identities with unprefixed base58, not digests or public keys. Public JSON uses canonical strings and rejects old hex aliases. Private recovery keys and pairing tickets keep their existing representation.

Genesis anchors the repository's allowed algorithms. Parsing a registered value does not authorize execution: the policy and implemented scope/deadline checks must also pass. Current local protection, index envelopes and key wrapping use XChaCha20-Poly1305; other registered AEADs are content-only. Runtime policy switching is not implemented. Pairing retains its keyed BLAKE3 MAC/SAS, rather than adding an independent signature.

`deprecated` marks an algorithm scheduled for retirement. Before a deadline, or when none is set, a deprecated entry remains usable in an implemented scope. A deadline is an optional UTC instant written as RFC 3339 with `Z`; code stores it as `deprecated_after_epoch_ms: Option<u64>` (Unix epoch milliseconds). Registry validation through `ensure_usable_at(scope, now_epoch_ms)` rejects an expired entry when `now_epoch_ms >= deprecated_after_epoch_ms`, including the exact boundary. Unknown algorithms and algorithms unimplemented for the requested scope also fail explicitly. Parsing a registered SHA digest does not authorize its use for content or identities. No failure selects another algorithm or ignores a deadline.

Copied or manually constructed registration metadata must match the static entry's family, ID, and text identifier. It may restrict supported uses or shorten a deadline, but cannot enable an unimplemented use or extend the registry deadline.
