Dustin-Ray / capyCRYPT

An experimental high-performance cryptosystem.
MIT License
12 stars 1 forks source link

sidechannel: make any comparisons fixed time #65

Open Dustin-Ray opened 4 months ago

Dustin-Ray commented 4 months ago

There a few places where we need to check the output of an algorithm. This is usually an equality between two arrays of bytes. It is possible that this check might reveal information about the bytes being operated over.

We should implement a fixed time equality check as we do in the curve crate for conducting equality checks between field elements.

Usually we are just comparing two fixed sized byte arrays which are obtained from hash outputs used to validate that a certain process was carried out correctly, so the current impact is minimal.

cpwallah commented 4 months ago

hi can i try this @drcapybara

Dustin-Ray commented 4 months ago

@cpwallah hey right on thanks for the help. so check this out:

if self.digest == new_t {
    Ok(())
} else {
    xor_bytes(&mut self.msg, &m);
    Err(OperationError::SHA3DecryptionFailure)

specifically this line here:

if self.digest == new_t

so here, we just did a bunch of cryptographic operations to produce a decryption, and we want to check that the decryption is correct by comparing the hash with the tag that was sent to us. this ticket is addressing the comparison operation between the two byte arrays. so we need a way to check in fixed time if these byte arrays are equal to each other.

this should be a pretty simple fix. we can use the subtle crate which provides a simple method we can use. so youll need to do the following:

cargo add subtle
use subtle::ConstantTimeEq;

if self.digest.ct_eq(new_t).into() {
          Ok(())
      } else {
          xor_bytes(&mut self.msg, m);
          Err(OperationError::SHA3DecryptionFailure)
      }

That should be all you need to do! For content, subtle is a crate developed by the curve-dalek authors in order to provide fixed-time equality checks. it accomplishes this check by performing arithmetic on the bytes and then checking a result, instead of moving through the bytes one by one. this may incur slight overhead but we will probably only use this on small hashes which are pretty small anyways.