96 lines
4.0 KiB
Markdown
96 lines
4.0 KiB
Markdown
# HeroDB AGE Cryptography
|
|
|
|
HeroDB provides AGE-based asymmetric encryption and digital signatures over the Redis protocol using X25519 for encryption and Ed25519 for signatures. Keys can be used in stateless (ephemeral) or key-managed (persistent, named) modes.
|
|
|
|
In key-managed mode, HeroDB uses a unified keypair concept: a single Ed25519 signing key is deterministically derived into X25519 keys for encryption, allowing one keypair to handle both encryption and signatures transparently.
|
|
|
|
## Cryptographic Algorithms
|
|
|
|
### X25519 (Encryption)
|
|
- Elliptic-curve Diffie-Hellman key exchange for symmetric key derivation.
|
|
- Used for encrypting/decrypting messages.
|
|
|
|
### Ed25519 (Signatures)
|
|
- EdDSA digital signatures for message authentication.
|
|
- Used for signing/verifying messages.
|
|
|
|
### Key Derivation
|
|
Ed25519 signing keys are deterministically converted to X25519 keys for encryption. This enables a single keypair to support both operations without additional keys. Derivation uses the Ed25519 secret scalar clamped for X25519.
|
|
|
|
In named keypairs, Ed25519 keys are stored, and X25519 keys are derived on-demand and cached.
|
|
|
|
## Stateless Mode (Ephemeral Keys)
|
|
No server-side storage; keys are provided with each command.
|
|
|
|
Available commands:
|
|
- `AGE GENENC`: Generate ephemeral X25519 keypair. Returns `[recipient, identity]`.
|
|
- `AGE GENSIGN`: Generate ephemeral Ed25519 keypair. Returns `[verify_pub, sign_secret]`.
|
|
- `AGE ENCRYPT <recipient> <message>`: Encrypt message. Returns base64 ciphertext.
|
|
- `AGE DECRYPT <identity> <ciphertext_b64>`: Decrypt ciphertext. Returns plaintext.
|
|
- `AGE SIGN <sign_secret> <message>`: Sign message. Returns base64 signature.
|
|
- `AGE VERIFY <verify_pub> <message> <signature_b64>`: Verify signature. Returns 1 (valid) or 0 (invalid).
|
|
|
|
Example:
|
|
```bash
|
|
redis-cli AGE GENENC
|
|
# → 1) "age1qz..." # recipient (X25519 public)
|
|
# 2) "AGE-SECRET-KEY-1..." # identity (X25519 secret)
|
|
|
|
redis-cli AGE ENCRYPT "age1qz..." "hello"
|
|
# → base64_ciphertext
|
|
|
|
redis-cli AGE DECRYPT "AGE-SECRET-KEY-1..." base64_ciphertext
|
|
# → "hello"
|
|
```
|
|
|
|
## Key-Managed Mode (Persistent Named Keys)
|
|
Keys are stored server-side under names. Supports unified keypairs for both encryption and signatures.
|
|
|
|
Available commands:
|
|
- `AGE KEYGEN <name>`: Generate and store unified keypair. Returns `[recipient, identity]` in age format.
|
|
- `AGE SIGNKEYGEN <name>`: Generate and store Ed25519 signing keypair. Returns `[verify_pub, sign_secret]`.
|
|
- `AGE ENCRYPTNAME <name> <message>`: Encrypt with named key. Returns base64 ciphertext.
|
|
- `AGE DECRYPTNAME <name> <ciphertext_b64>`: Decrypt with named key. Returns plaintext.
|
|
- `AGE SIGNNAME <name> <message>`: Sign with named key. Returns base64 signature.
|
|
- `AGE VERIFYNAME <name> <message> <signature_b64>`: Verify with named key. Returns 1 or 0.
|
|
- `AGE LIST`: List all stored key names. Returns sorted array of names.
|
|
|
|
### AGE LIST Output
|
|
Returns a flat, deduplicated, sorted array of key names (strings). Each name corresponds to a stored keypair, which may include encryption keys (X25519), signing keys (Ed25519), or both.
|
|
|
|
Output format: `["name1", "name2", ...]`
|
|
|
|
Example:
|
|
```bash
|
|
redis-cli AGE LIST
|
|
# → 1) "<named_keypair_1>"
|
|
# 2) "<named_keypair_2>"
|
|
```
|
|
|
|
For unified keypairs (from `AGE KEYGEN`), the name handles both encryption (derived X25519) and signatures (stored Ed25519) transparently.
|
|
|
|
Example with named keys:
|
|
```bash
|
|
redis-cli AGE KEYGEN app1
|
|
# → 1) "age1..." # recipient
|
|
# 2) "AGE-SECRET-KEY-1..." # identity
|
|
|
|
redis-cli AGE ENCRYPTNAME app1 "secret message"
|
|
# → base64_ciphertext
|
|
|
|
redis-cli AGE DECRYPTNAME app1 base64_ciphertext
|
|
# → "secret message"
|
|
|
|
redis-cli AGE SIGNNAME app1 "message"
|
|
# → base64_signature
|
|
|
|
redis-cli AGE VERIFYNAME app1 "message" base64_signature
|
|
# → 1
|
|
```
|
|
|
|
## Choosing a Mode
|
|
- **Stateless**: For ad-hoc operations without persistence; client manages keys.
|
|
- **Key-managed**: For centralized key lifecycle; server stores keys for convenience and discoverability.
|
|
|
|
Implementation: [herodb/src/age.rs](herodb/src/age.rs) <br>
|
|
Tests: [herodb/tests/usage_suite.rs](herodb/tests/usage_suite.rs) |