# ps-cypher
Convergent encryption with ChaCha20-Poly1305, zstd, and Reed-Solomon ECC.
## Scheme
- The encryption key is the hash of the plaintext (`ps-hash`): the `ChaCha20`
key is the hash's 32-byte digest, and the nonce is derived from the hash's
parity bytes.
- The plaintext is compressed deterministically (zstd level 7 via
`ps-compress`) before encryption.
- The ciphertext is Reed-Solomon encoded (`ps-ecc`), so up to 12 corrupted
bytes per codeword are repaired transparently during decryption.
- Identical inputs therefore always produce identical ciphertexts, keys, and
hashes, which enables content-addressed deduplication of encrypted data.
- `decrypt` re-hashes the decrypted data and fails with `KeyMismatch` unless
it hashes to the decryption key, so a successful decryption returns
exactly the data that produced the key.
## Example
```rust
use ps_cypher::{decrypt, encrypt};
let encrypted = encrypt(b"example payload")?;
let decrypted = decrypt(&encrypted.bytes, &encrypted.key)?;
assert_eq!(&*decrypted, b"example payload");
# Ok::<(), Box<dyn std::error::Error>>(())
```
## Security caveats
Convergent encryption is deterministic by design, which leaks information
that a randomized cipher would not:
- **Plaintext equality**: identical plaintexts encrypt to identical
ciphertexts, so an observer learns when two stored objects are equal.
- **Confirmation and dictionary attacks**: anyone who can guess a plaintext
can encrypt the guess and compare ciphertexts, confirming whether it is
stored. Low-entropy data is therefore not confidential against an
adversary who can enumerate candidates.
- **Length leakage**: the ciphertext length reveals the compressed size of
the plaintext, i.e., its length and compressibility.
- **`validate_ecc` is not authentication**: it is an unkeyed checksum that
detects accidental corruption only, and it returns `false` for
corrupted-but-correctable data that `decrypt` still accepts. Tampering is
detected by the Poly1305 tag during `decrypt`, and the decrypted data is
additionally verified to hash to the decryption key.