mirror of
https://github.com/logos-storage/lioness_blockcipher.git
synced 2026-05-18 18:49:28 +00:00
impl enc/dec with auth
This commit is contained in:
parent
5cb804403e
commit
9ff3fa3b49
@ -63,8 +63,8 @@ fn main() -> anyhow::Result<()> {
|
||||
Some notes:
|
||||
|
||||
- Encryption and decryption are both in-place for now.
|
||||
- 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)
|
||||
- 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 ...
|
||||
|
||||
@ -9,7 +9,7 @@ type TestLioness = Lioness::<
|
||||
TurboShake128Kdf
|
||||
>;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
fn prepend_before_enc() -> Result<()>{
|
||||
let mut key: Key256 = Default::default();
|
||||
OsRng.fill_bytes(&mut key);
|
||||
let cipher: TestLioness = Lioness::new(&key)?;
|
||||
@ -26,9 +26,37 @@ fn main() -> Result<()> {
|
||||
|
||||
cipher.decrypt_in_place(&mut block)?;
|
||||
|
||||
if block[..SEC_PARAM].iter().all(|&b| b != 0) {
|
||||
println!("tampering detected i.e. zero-prefix check failed");
|
||||
for b in block[..SEC_PARAM].iter(){
|
||||
if *b != 0{
|
||||
println!("tampering detected i.e. zero-prefix check failed");
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call_enc_auth() -> Result<()>{
|
||||
let mut key: Key256 = Default::default();
|
||||
OsRng.fill_bytes(&mut key);
|
||||
let cipher: TestLioness = Lioness::new(&key)?;
|
||||
|
||||
let mut payload = [0x84u8; 4096];
|
||||
|
||||
// let mut block = plaintext.clone();
|
||||
let mut ciphertext = cipher.encrypt_auth(&mut payload)?;
|
||||
|
||||
// tamper with the ciphertext
|
||||
ciphertext[21] ^= 0x01;
|
||||
|
||||
assert!(cipher.decrypt_auth(&mut ciphertext).is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
// prepend before calling the lioness encryption
|
||||
prepend_before_enc()?;
|
||||
// use built-in functions
|
||||
call_enc_auth()
|
||||
}
|
||||
|
||||
@ -60,10 +60,10 @@ impl LionessKdf for HkdfSha256{
|
||||
|
||||
pub struct DomSepSha256Kdf;
|
||||
const LIONESS_ROUND_KEY_DOMAINS: [&[u8]; 4] = [
|
||||
b"Lioness-key1",
|
||||
b"Lioness-key2",
|
||||
b"Lioness-key3",
|
||||
b"Lionesskey4",
|
||||
b"lioness-key1",
|
||||
b"lioness-key2",
|
||||
b"lioness-key3",
|
||||
b"lionesskey4",
|
||||
];
|
||||
impl LionessKdf for DomSepSha256Kdf {
|
||||
fn derive_keys(master_key: &Key256) -> anyhow::Result<RoundKeys> {
|
||||
|
||||
@ -121,10 +121,17 @@ impl<
|
||||
}
|
||||
|
||||
/// Same as `encrypt_in_place` but prepends the plaintext with `SEC_PARAM` bytes of zeros
|
||||
pub fn encrypt_in_place_auth(&self, _block: &mut [u8]) -> Result<()> {
|
||||
let mut plaintext = vec![0u8; SEC_PARAM];
|
||||
plaintext.extend_from_slice(_block);
|
||||
todo!()
|
||||
/// WARNING: The output ciphertext is 16 bytes bigger than the input block
|
||||
/// Here we can accept 48 bytes since we add 16-bytes zero prefix.
|
||||
pub fn encrypt_auth(&self, plaintext: &mut [u8]) -> Result<Vec<u8>> {
|
||||
// Here we can accept at least 48 bytes since we add 16-bytes zero prefix.
|
||||
if plaintext.len() < 2*K_256 - SEC_PARAM {
|
||||
return Err(anyhow!("block must be at least {} bytes", 2*K_256 - SEC_PARAM));
|
||||
}
|
||||
let mut block = vec![0u8; SEC_PARAM + plaintext.len()];
|
||||
block[SEC_PARAM..].copy_from_slice(plaintext);
|
||||
self.encrypt_in_place(&mut block)?;
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
/// Decrypt a single wide block in place.
|
||||
@ -150,8 +157,19 @@ impl<
|
||||
}
|
||||
|
||||
/// Same as `decrypt_in_place` with added check for `SEC_PARAM`-bytes zero prefix
|
||||
pub fn decrypt_in_place_auth(&self, _block: &mut [u8]) -> Result<()> {
|
||||
todo!()
|
||||
/// returns either the plaintext without the zero prefix or throws an error
|
||||
pub fn decrypt_auth(&self, block: &mut [u8]) -> Result<Vec<u8>> {
|
||||
if block.len() < 2*K_256 {
|
||||
return Err(anyhow!("blocks must be at least {} bytes", 2*K_256));
|
||||
}
|
||||
self.decrypt_in_place(block)?;
|
||||
for b in block[..SEC_PARAM].iter(){
|
||||
if *b != 0{
|
||||
return Err(anyhow!("ciphertext tampering detected!"))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(block.to_vec().split_off(SEC_PARAM))
|
||||
}
|
||||
|
||||
/// apply the steam cipher round
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user