2026-04-06 08:01:00 +02:00
### Lioness large-block cipher with ChaCha20, Blake2b, and Turboshake.
### 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 large block cipher built from
2026-05-01 16:08:57 +03:00
- `S` : Stream cipher,
- `H` : Keyed-Hash function,
- `K` : Key derivation function (KDF) to derive the 4 internal round keys
2026-04-06 08:01:00 +02:00
2026-05-01 16:08:57 +03:00
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 )
2026-04-06 08:01:00 +02:00
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
2026-05-01 16:08:57 +03:00
use rand_core::{OsRng, RngCore};
use lioness_blockcipher::prelude::*;
type TestLioness = Lioness::<
ChaCha20StreamCipher,
KeyedBlake2b,
TurboShake128Kdf
>;
2026-04-06 08:01:00 +02:00
fn main() -> anyhow::Result< ()> {
2026-05-01 16:08:57 +03:00
let mut key: Key256 = Default::default();
OsRng.fill_bytes(& mut key);
2026-04-06 08:01:00 +02:00
2026-05-01 16:08:57 +03:00
let cipher: TestLioness = Lioness::new(&key)?;
2026-04-06 08:01:00 +02:00
2026-05-01 16:08:57 +03:00
// Blocks must be at >64 bytes long
let mut block = vec![0x84u8; 65];
2026-04-06 08:01:00 +02:00
let original = block.clone();
cipher.encrypt_in_place(& mut block)?;
cipher.decrypt_in_place(& mut block)?;
2026-05-01 16:08:57 +03:00
2026-04-06 08:01:00 +02:00
assert_eq!(block, original);
2026-05-01 16:08:57 +03:00
println!("success!");
2026-04-06 08:01:00 +02:00
Ok(())
}
```
Some notes:
- Encryption and decryption are both in-place for now.
2026-05-01 16:08:57 +03:00
- The block length need to be bigger than `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_in_place_auth` which prepends the plaintext with 128-bits zeros. Also use `decrypt_in_place_auth` to check the zeros after decryption. see [authentication example ](./examples/auth )
2026-04-06 08:01:00 +02:00
### TODO
2026-05-01 16:08:57 +03:00
- [x] Add more tests, examples, and benchmarks ...
- [x] Make it generic for any compatible cipher, keyed_hash, and KDF.
2026-04-12 10:53:34 +02:00
- [ ] Compare with existing implementation + maybe with Haskel when available.
2026-05-01 16:08:57 +03:00
- [x] Add function which prepend the plaintext with k-zeros and checks authenticity after decryption.
2026-04-06 08:01:00 +02:00
- [ ] impl enc and dec to the API to work beside encrypt_in_place and decrypt_in_place.
- ...