Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: sliding window message encryption and decryption #20

Open
Dustin-Ray opened this issue Oct 17, 2023 · 5 comments
Open

feature: sliding window message encryption and decryption #20

Dustin-Ray opened this issue Oct 17, 2023 · 5 comments
Assignees
Labels
good first issue Good for newcomers improvement Improve the design, usability, safety, and/or efficiency of the library Medium Effort Nothing too crazy. Maybe some new concepts and design patterns. 1 - 2 weeks of casual effort.

Comments

@Dustin-Ray
Copy link
Owner

Dustin-Ray commented Oct 17, 2023

current design constructs a "keystream" exactly the length of the message, then XORs the two in place. This implies that the size of the message is doubled on the heap to accommodate for the keystream. We should update this so that each time sponge_squeeze is called, encrypt/decrypt will act as a sliding window over the message. This will ensure better performance and constant memory usage on large inputs.

@Dustin-Ray
Copy link
Owner Author

sponge_squeeze is serial by design and cannot be run in parallel.

@Dustin-Ray Dustin-Ray changed the title batch message encryption and decryption fix: batch message encryption and decryption Oct 18, 2023
@Dustin-Ray Dustin-Ray changed the title fix: batch message encryption and decryption feature: sliding window message encryption and decryption Oct 18, 2023
@Dustin-Ray Dustin-Ray added feature Add new functionality to the library Medium Effort Nothing too crazy. Maybe some new concepts and design patterns. 1 - 2 weeks of casual effort. labels Oct 20, 2023
@Dustin-Ray
Copy link
Owner Author

Dustin-Ray commented Oct 27, 2023

This fix is easy and will just require some code reorganization. Check out pw_encrypt for example:

    fn pw_encrypt(&mut self, pw: &[u8], d: u64) {
        let z = get_random_bytes(512);
        let mut ke_ka = z.clone();
        ke_ka.append(&mut pw.to_owned());
        let ke_ka = kmac_xof(&mut ke_ka, &vec![], 1024, "S", d);
        let ke = &mut ke_ka[..64].to_vec();
        let ka = &mut ke_ka[64..].to_vec();
        self.digest = Some(kmac_xof(ka, &self.msg, 512, "SKA", d));
        let c = kmac_xof(ke, &vec![], (self.msg.len() * 8) as u64, "SKE", d);
        xor_bytes(&mut self.msg, &c);
        self.sym_nonce = Some(z);
    }

Can you spot the problem? Its right here:

let c = kmac_xof(ke, &vec![], (self.msg.len() * 8) as u64, "SKE", d);

we create a key exactly the size of the message. For a small message like "Hello, Dave" This is no problem. What if we want to encrypt an entire hard disk? This solution immediately fails because we require in memory a single key exactly the size of the message, even though we eventually XOR the key in place into the original message.

What we need to do is take advantage of the serial nature of sponge_squeeze and XOR each squeezed block into the message, instead of creating c on the heap.

heres an example of how we can carry this out:

fn main() {
    let mut large_keystream = vec![0xAA; 1024];  // Example large keystream (initialized with 0xAA for illustration)
    let block_size = 64;  // Assume the block size is 64 bytes

    // Simulate generating and XORing blocks
    for i in 0..(large_keystream.len() / block_size) {
        let block = sponge_squeeze();
        let start = i * block_size;
        let end = start + block_size;
        xor_in_place(&mut large_keystream[start..end], &block);
    }
}

This code could happen inside of any function we are modifying, but the correct solution ends up in:

sha3::{aux_functions::{byte_utils::{sliding_window_xor}}

@Dustin-Ray
Copy link
Owner Author

This would probably be a different issue, but we need to keep track of the operation and be able to revert it in case it is interrupted or fails. This would involve:

  1. Keeping a copy of the current block before we XOR
  2. keeping track of the position of the last successful block
  3. be able to recover and revert the XOR in case of failure

@Dustin-Ray Dustin-Ray added good first issue Good for newcomers improvement Improve the design, usability, safety, and/or efficiency of the library and removed feature Add new functionality to the library labels Oct 27, 2023
@Hyunggilwoo Hyunggilwoo self-assigned this Mar 2, 2024
@Hyunggilwoo
Copy link
Collaborator

I am trying to understand where in the sponge::{sponge_squeeze} requires an update to add this feature.
I read the sponge::{sponge_squeeze} and other functions relevant to creating byte_utils::{sliding_window_xor}.

@Dustin-Ray
Copy link
Owner Author

I am trying to understand where in the sponge::{sponge_squeeze} requires an update to add this feature.

great question, its happening right here:

pub(crate) fn sponge_squeeze<S: BitLength + ?Sized>(
    s: &mut [u64; 25],
    bit_length: &S,
    rate: Rate,
) -> Vec<u8> {
    let mut out: Vec<u8> = Vec::new(); //FIPS 202 Algorithm 8 Step 8
    let block_size: usize = (rate.value / 64) as usize;
    while out.len() * 8 < bit_length.bit_length() as usize {
        out.append(&mut state_to_byte_array(&s[0..block_size]));
        keccakf_1600(s); //FIPS 202 Algorithm 8 Step 10
    }
    out.truncate((bit_length.bit_length() / 8) as usize);
    out
}

whats happening here is that we are passed in a bit length value which determines how many bits to output from the sponge. instead of this, we actually need to update this function a bit.

it needs to be called finalize and instead of generating the output all at once, it simply needs to only produce one block of output at a time when it is called. it needs to save its state in order to do this correctly in the way that it does now.

fixing this issue first requires fixing #18, but that issue is a little easier and simpler than this.

@Hyunggilwoo Hyunggilwoo removed their assignment Mar 3, 2024
Hyunggilwoo added a commit that referenced this issue Mar 4, 2024
What is next:
For the upcoming issue #20, make `finalize()` maintain some state
and produce a single block instead.
@Hyunggilwoo Hyunggilwoo self-assigned this Mar 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers improvement Improve the design, usability, safety, and/or efficiency of the library Medium Effort Nothing too crazy. Maybe some new concepts and design patterns. 1 - 2 weeks of casual effort.
Projects
None yet
Development

No branches or pull requests

2 participants