What protects what
Every product's cryptography in one place: what each algorithm protects, the suite id written into what it produces, and how it fares against a large quantum computer. Where something is still classical, this page says so. The same inventory is at /cbom.json as a CycloneDX 1.6 CBOM, and tilldev secrets crypto shows it for your workspace.
How to read it
| Stance | What it means |
|---|---|
| hybrid | Hybrid: holds while either half does |
| post-quantum | Post-quantum |
| symmetric | Symmetric: quantum-adequate at 256 bits |
| hash | Hash: quantum-adequate |
| classical | Classical: a large quantum computer breaks it |
| none | Not encrypted by us |
“Hybrid” pairs a classical algorithm with a post-quantum one so that breaking it needs both broken. “Symmetric” and “hash” entries use 256-bit keys or outputs, which a quantum computer weakens but does not break. Nothing here claims to be quantum-proof.
Product by product
TillSecrets
| Protects | How | Stance |
|---|---|---|
| Secret values, backend and sync credentials, presigned-call templates, dropped values | AES-256-GCM under the workspace’s data key · aead-aes256gcm.v1 | symmetric |
| The workspace’s data key | AES-256-GCM under a master key kept outside the database · aead-aes256gcm.v1 | symmetric |
| Value fingerprints (change detection, leak matching) | HMAC-SHA256 keyed by the data key | symmetric |
| Pulls and leases in transit, inside TLS | X-Wing, then HKDF-SHA256, then AES-256-GCM, bound to the request · xwing-aes256gcm.v1 | hybrid |
| Service, agent, presigned-call and drop-link tokens | Random, stored as SHA-256 | hash |
| Workload sign-in with a platform token or a signed AWS request | The issuer’s RSA, ECDSA or EdDSA signature; AWS SigV4, checked by AWS The platform chooses the algorithm. The token sent back is under X-Wing. | classical |
| Workload sign-in by host key | A challenge encrypted to the host’s X-Wing key, then HKDF-SHA256 and AES-256-GCM · xwing-aes256gcm.v1 | hybrid |
| A bound presigned call’s machine proof | Ed25519 signature by the machine’s key | classical |
| Requests to your own credential endpoint | HMAC-SHA256 signature header | symmetric |
| Approvals of sensitive actions | A passkey, or a paired phone signing with Ed25519 | classical |
| Keys the vault makes for you | Ed25519, RSA, ML-DSA-65, SLH-DSA, ML-KEM-768, X-Wing, hybrid ML-DSA-65 + Ed25519 Your keys, for your systems; the vault does not use them. | post-quantum |
TillAuth
| Protects | How | Stance |
|---|---|---|
| Your users’ passwords | Argon2id (64 MiB, 3 passes, 4 lanes), peppered; imported bcrypt and PBKDF2 hashes are upgraded at sign-in | hash |
| Access and ID tokens | EdDSA (Ed25519) signatures, keys published as JWKS | classical |
| OAuth and OIDC client secrets, authenticator secrets, linked-account tokens, webhook secrets | AES-256-GCM under a per-app data key, itself under a master key · aead-aes256gcm.v1 | symmetric |
| Webhook deliveries | HMAC-SHA256 signature | symmetric |
| Passkey sign-in | WebAuthn: the authenticator’s Ed25519, ECDSA P-256 or RSA key | classical |
| Authenticator codes | TOTP (RFC 6238), HMAC-SHA1 | symmetric |
TillPulse
| Protects | How | Stance |
|---|---|---|
| Integration credentials (trackers, SSO, vendor accounts) | AES-256-GCM under a dedicated key · aead-aes256gcm.v1 | symmetric |
TillShield
| Protects | How | Stance |
|---|---|---|
| TillGate challenge and pass state | HMAC-SHA256 | symmetric |
| Device attestation tokens TillGate accepts | Ed25519 signature by the issuer | classical |
TillForge
| Protects | How | Stance |
|---|---|---|
| Mirror credentials and webhook secrets | AES-256-GCM under a per-workspace data key, itself under a master key · aead-aes256gcm.v1 | symmetric |
| Webhook deliveries | HMAC-SHA256 signature | symmetric |
| Git over SSH | mlkem768x25519-sha256 key exchange; Ed25519 host key The key exchange is hybrid; the host key signature is classical. | hybrid |
| Commit and tag signatures made with SSH keys | SSH signatures (Ed25519, ECDSA, RSA) verified against keys registered to the author or committer A branch can refuse them and accept hybrid signatures only. | classical |
| Commit and tag signatures made with hybrid keys, and the commits TillForge writes (merges, browser edits) | ML-DSA-65 and Ed25519 both sign the SSH signature message (SHA-512); both must verify against a key registered to the author or committer | hybrid |
| The git server’s copy of access and branch policy, used while the control plane is unreachable | Ed25519 and ML-DSA-65 both sign; the git server checks both against a pinned key | hybrid |
| Repositories on the git server: contents, file names, LFS objects | Linux fscrypt v2 with a 512-bit key per organization: AES-256-XTS for contents, AES-256-CTS for names, per-file keys by HKDF-SHA512 File sizes, counts and timestamps are not hidden, and the running git server reads data decrypted. | symmetric |
| Each organization’s repository key, held by the control plane | AES-256-GCM under a per-workspace data key, itself under a master key; released only to a git server that holds the organization’s repositories or serves its region, from that server’s own addresses · aead-aes256gcm.v1 | symmetric |
| Each git server’s own credential | Checked against a SHA-256 hash; kept for calls to the server under AES-256-GCM with a master key · aead-aes256gcm.v1 | symmetric |
| Repository backups | AES-256-GCM in 64 KiB chunks under a key derived by HKDF-SHA256 from the organization’s repository key | symmetric |
TillCache
| Protects | How | Stance |
|---|---|---|
| Your own backend’s credentials | AES-256-GCM under a master key · aead-aes256gcm.v1 | symmetric |
| Access tokens | Random, stored as SHA-256 | hash |
TillNotary
| Protects | How | Stance |
|---|---|---|
| Checkpoints and timestamps | Ed25519 and ML-DSA-65 both sign; a SHA-256 Merkle tree (RFC 9162) · sig-ed25519-mldsa65-sha256.v1 | hybrid |
| Logs on the higher profile | Ed25519 and ML-DSA-87; a SHA-384 Merkle tree · sig-ed25519-mldsa87-sha384.v1 | hybrid |
TillArk
| Protects | How | Stance |
|---|---|---|
| Connection strings, target and repository keys | AES-256-GCM under the workspace’s data key · aead-aes256gcm.v1 | symmetric |
| Credentials sent to agents | X-Wing, then HKDF-SHA256, then AES-256-GCM, bound to the agent and job · xwing-aes256gcm.v1 | hybrid |
| Work sent to agents and backup manifests | ML-DSA-65 and Ed25519 both sign | hybrid |
| Logical dumps, files and ClickHouse table parts | restic: AES-256-CTR + Poly1305-AES, in the agent before upload | symmetric |
| Base backups and WAL | WAL-G: XChaCha20-Poly1305 (libsodium), in the agent before upload | symmetric |
| Base backups and WAL | pgBackRest: AES-256-CBC, in the agent before upload. CBC isn’t authenticated, so a restore checks every file against SHA-1 checksums the signed manifest covers, and each WAL segment against the SHA-1 it was archived under | symmetric |
TillDev
| Protects | How | Stance |
|---|---|---|
| AI provider keys | AES-256-GCM under an HKDF-SHA256 key derived from the workspace’s data key, the credential and, for a personal key, its owner · aead-aes256gcm.v1 | symmetric |
| Dashboard sessions | RS256 signed tokens | classical |
| API keys | Random, stored as SHA-256 | hash |
| Dashboard authenticator secrets | AES-256-GCM under a dedicated key · aead-aes256gcm.v1 | symmetric |
TLS and SSH, measured
Measured from outside on 2026-09-30. Every endpoint below agrees on the hybrid key exchange when the client offers it; current browsers, OpenSSL 3.5+, Node 24 and OpenSSH 10 do.
| Endpoint | Key exchange | Serves |
|---|---|---|
https://tilldev.dev | TLS 1.3 with X25519MLKEM768 when the client offers it; otherwise X25519, and TLS 1.2 is still accepted with a classical key exchange | TillDev, TillSecrets, TillPulse, TillShield, TillForge, TillNotary, TillArk |
https://secrets.tilldev.dev | TLS 1.3 with X25519MLKEM768 when the client offers it; otherwise X25519, and TLS 1.2 is still accepted with a classical key exchange | TillSecrets |
https://auth.tilldev.dev | TLS 1.3 with X25519MLKEM768 when the client offers it; otherwise X25519, and TLS 1.2 is still accepted with a classical key exchange | TillAuth |
https://git.tilldev.dev | TLS 1.3 with X25519MLKEM768 when the client offers it; otherwise X25519, and TLS 1.2 is still accepted with a classical key exchange | TillForge |
ssh://git.tilldev.dev:2222 | mlkem768x25519-sha256; Ed25519 host key | TillForge |
https://cache.tilldev.dev | TLS 1.3 with X25519MLKEM768 when the client offers it; otherwise X25519, and TLS 1.2 is still accepted with a classical key exchange | TillCache |
https://ingest.tilldev.dev | TLS 1.3 with X25519MLKEM768 when the client offers it; otherwise X25519, and TLS 1.2 is still accepted with a classical key exchange | TillPulse |
Check it yourself:
# TLS: offer only the hybrid group; the handshake fails if the server can't do it
openssl s_client -connect secrets.tilldev.dev:443 -groups X25519MLKEM768 -brief </dev/null
# Negotiated TLS1.3 group: X25519MLKEM768
# SSH to TillForge: the key exchange the server picks
ssh -p 2222 -v git@git.tilldev.dev 2>&1 | grep 'kex: algorithm'
# debug1: kex: algorithm: mlkem768x25519-sha256
# From the CLI: what this machine negotiates, and what your workspace's secrets are under
tilldev secrets crypto --tlsEvery ciphertext names its suite
Ciphertext stored by TillSecrets, TillForge, TillCache, TillArk, TillAuth, for AI provider keys, TillPulse integration credentials and dashboard authenticator secrets starts with the id of the suite that made it, so a stored value says how to open it and a new suite can be added without guessing:
aead-aes256gcm.v1|<iv hex>:<tag hex>:<ciphertext hex> at rest
xwing-aes256gcm.v1|<KEM ciphertext>.<nonce>.<ciphertext + tag> delivered to a hostA value without the prefix was written before suite ids, with the same AES-256-GCM. It stays readable. In TillSecrets, rotating the workspace data key rewrites everything with the prefix, and the dashboard's Cryptography page shows how many items in each store are still unlabelled. Rotating a TillAuth app's data key does the same for that app. An id the reader doesn't know is refused, not guessed at. TillNotary checkpoints carry sig-ed25519-mldsa65-sha256.v1 or sig-ed25519-mldsa87-sha384.v1.
Still classical
These use signatures a large quantum computer could forge:
- TillSecrets: workload sign-in with a platform token or a signed AWS request (The issuer’s RSA, ECDSA or EdDSA signature; AWS SigV4, checked by AWS).
- TillSecrets: a bound presigned call’s machine proof (Ed25519 signature by the machine’s key).
- TillSecrets: approvals of sensitive actions (A passkey, or a paired phone signing with Ed25519).
- TillDev: dashboard sessions (RS256 signed tokens).
- TillAuth: access and ID tokens (EdDSA (Ed25519) signatures, keys published as JWKS).
- TillAuth: passkey sign-in (WebAuthn: the authenticator’s Ed25519, ECDSA P-256 or RSA key).
- TillShield: device attestation tokens TillGate accepts (Ed25519 signature by the issuer).
- TillForge: commit and tag signatures made with SSH keys (SSH signatures (Ed25519, ECDSA, RSA) verified against keys registered to the author or committer).
Signatures matter at the moment they are checked, so a future quantum computer can't reach back and forge a sign-in that already happened. The risk is to long-lived keys once such a computer exists. Browsers and WebAuthn authenticators don't offer post-quantum signatures yet.
Machine-readable
/cbom.json is this page as a CycloneDX 1.6 cryptography bill of materials: algorithms and protocols as cryptographic-asset components, with their primitive, mode, parameter set, OID and NIST quantum security level, and each protected thing as a data component that depends on them. Its version is the inventory revision (now 1); feed it to any tool that reads CycloneDX.
curl -s https://tilldev.dev/cbom.json | jq '.components[] | select(.type == "cryptographic-asset") | .name'For your own keys, see post-quantum keys in TillSecrets.