RGP
Relatively Good Privacy
Ciphersuite
- Blake2s256 for hashing
- Ed25519 for signatures
- X25519 for shared secrets
- XChaCha20 for content keys
- XChaCha20Poly1305 for content
Modes
There are currently three supported modes: Dh (Diffie-Hellman), Hmac, and Session. All modes provide the ability to sign content and verify the sender. Deniability is preserved by signing the plaintext and encrypting the signature alongside the plaintext.
Diffie-Hellman
Dh mode provides forward secrecy as it generates a fresh/random content key for each message. The content key is then encrypted with each recipients' shared secrets. But with the added security of forward secrecy comes the computational and storage overhead of encrypting and attaching the encrypted content key for each recipient.
let = generate_fingerprint;
let = generate_dh_keys;
let = generate_dh_keys;
let mut pub_keys = vec!;
// 8mb
let content = vec!;
// add another 20,000 recipients
for _ in 0..20_000
// encrypt Alice's message for all recipients
let = encrypt
.unwrap;
// extract for Bob
extract_for_key_position_mut.unwrap;
// decrypt Alice's message for Bob
let = decrypt
.unwrap;
assert_eq!;
assert_eq!;
Internal Process:
- Generate one-time components
- nonce
- content key
- Sign plaintext to generate content signature
- Encrypt plaintext and content signature with content key
- Encrypt content key for all recipients
- Generate shared secret with recipient public key and sender private key
- Encrypt content key with shared secret
HMAC
Hmac mode, while it doesn't provide the same level of security as random key generation + per-recipient key encryption, it does enable backward secrecy, and when used with a non-constant key, it can enable forward secrecy when only the content key is compromised.
let = generate_fingerprint;
let hash_key = ; // use an actual key
let hash_value = ; // use an actual key
let content = vec!;
// encrypt Alice's message in `Hmac` mode
let = encrypt
.unwrap;
// decrypt Alice's message in `Hmac` mode
let = decrypt
.unwrap;
assert_eq!;
assert_eq!;
Internal Process:
- Generate nonce
- Hmac the content key
- Sign plaintext to generate content signature
- Encrypt plaintext and content signature with the hashed content key
Session
This mode provides no forward or backward secrecy, and uses the provided key "as is" without any modification. From an encryption perspective, this is essentially the same as just running the underlying symmetric cipher.
let = generate_fingerprint;
let session_key = ; // use an actual key
let content = vec!;
// encrypt Alice's message with a session key
let = encrypt
.unwrap;
// decrypt Alice's message with session key
let = decrypt
.unwrap;
assert_eq!;
Internal Process:
- Generate nonce
- Sign plaintext to generate content signature
- Encrypt plaintext and content signature with the provided content key, as is
Encrypted Format
- nonce = 24 bytes
- keys count (
Dhmode only)- int size = 2 bits
- count
- numbers 0-63 = 6 bits
- numbers >63 = 1-8 bytes (big endian int)
- encrypted copies of content key (
Dhmode only) = pub_keys.len() * 32 bytes - encrypted content = content.len()
- signature = 64 bytes (encrypted along with the content to preserve deniability)
- Poly1305 MAC = 16 bytes
- mode = 1 byte (0 for
Session| 1 forHmac| 2 forDh)
Performance
To check performance on your machine, run cargo bench. You can also view the latest benches in the GitHub CI workflow under job/Benchmark.
All benchmarks for multi-recipient payloads are for 20,000 recipients, and all benchmarks encrypt/sign/decrypt 8mb.
License
Security
THIS CODE HAS NOT BEEN AUDITED OR REVIEWED. USE AT YOUR OWN RISK.