74 lines
2.6 KiB
Markdown

### Lioness wide-block cipher.
### Warning
This code has not been formally audited, Use at your own risk or ask a cryptographers before use.
### Overview
[Lioness](https://www.cl.cam.ac.uk/~rja14/Papers/bear-lion.pdf) is a wide block cipher built from
- `S`: Stream cipher,
- `H`: Keyed-Hash function,
- `K`: Key derivation function (KDF) to derive the 4 internal round keys
Any secure compatible options and their combinations can work, in this crate we have the following options:
- `S`: AES-CTR-128, Chacha20
- `H`: keyed-Blake2b, HMAC-SHA-256, SHA-256 (with key prepend)
- `K`: TURBOSHAKE-128, SHAKE-128, HKDF-SHA-256, domain-seperated SHA-256
These primitives are imported from:
- [rustcrypto streamciphers](https://github.com/RustCrypto/stream-ciphers)
- [rustcrypto hashes](https://github.com/RustCrypto/hashes/tree/master)
The security of lioness reduce to the security of the underlying stream cipher or
the hash function.
See the [paper](https://www.cl.cam.ac.uk/~rja14/Papers/bear-lion.pdf) for more information.
### How to use
Here is an example of how to use the `Lioness_blockcipher` create.
Use a 32-byte master key and encrypt or decrypt a block in place:
```rust
use rand_core::{OsRng, RngCore};
use lioness_blockcipher::prelude::*;
type TestLioness = Lioness::<
Aes128CtrStreamCipher,
Sha256PrependKey,
DomSepSha256Kdf,
>;
fn main() -> anyhow::Result<()> {
let mut key: Key256 = Default::default();
OsRng.fill_bytes(&mut key);
let cipher: TestLioness = Lioness::new(&key)?;
// Blocks must be at >64 bytes long
let mut block = vec![0x84u8; 65];
let original = block.clone();
cipher.encrypt_in_place(&mut block)?;
cipher.decrypt_in_place(&mut block)?;
assert_eq!(block, original);
println!("success!");
Ok(())
}
```
Some notes:
- Encryption and decryption are both in-place for now.
- The block length need to be at least `64` bytes because Lioness splits the block into two where the left part is 32-byte, and the right part needs at least 16 bytes. might support small blocks in the future, but for Sphinx use-case, this should work.
- If you need authenticity, make sure to use `encrypt_auth` which prepends the plaintext with 128-bits zeros. Also use `decrypt_auth` to check the zeros after decryption. see [authentication example](./examples/auth)
### TODO
- [x] Add more tests, examples, and benchmarks ...
- [x] Make it generic for any compatible cipher, keyed_hash, and KDF.
- [x] Compare with existing Haskel implementation.
- [x] Add authenticated encryption and decryption which prepend the plaintext with k-zeros and checks authenticity after decryption.