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) |