Salsa20 Cipher - Rust

Feb 24, 2024
   44

It's important to note that while Salsa20 is a well-regarded and secure cipher, the security landscape is dynamic, and any cryptographic algorithm may become vulnerable to new attacks over time. Always use well-established and widely reviewed cryptographic primitives and protocols in real-world applications.


  1. Key Expansion:
  2. Salsa20 takes a 256-bit key and a 64-bit nonce (number used once) as input.
  3. The key and nonce are expanded using a series of bitwise operations and additions to create a 512-bit internal state.
  4. The expanded key is used to generate a stream of pseudorandom numbers.


2. Pseudorandom Number Generation:

  1. Salsa20 uses a quarter-round function applied repeatedly to its internal state to generate pseudorandom numbers.
  2. The quarter-round function involves various bitwise operations such as addition (XOR) and rotation.
  3. The function is applied 20 times in Salsa20/20 and 12 times in Salsa20/12, hence the names.


3. Stream Generation:

  1. The pseudorandom numbers generated by the quarter-round function are XORed with the plaintext to produce the ciphertext (or XORed with the ciphertext to produce the plaintext in the case of decryption).
  2. This XOR operation creates the keystream, which is then combined with the input data to produce the output.


4. Block Size and Counter:

  1. Salsa20 operates on 64-byte (512-bit) blocks.
  2. The 64-bit nonce and a 64-bit block counter are used to create a 128-bit block identifier, ensuring that the same key can be safely used with different nonces.
  3. The block counter is incremented for each block processed.

5. Security:

  1. Salsa20 is considered secure and has withstood extensive cryptanalysis.
  2. It provides a high level of security with a relatively simple and efficient design.

6. Usage:

  1. Salsa20 is commonly used in various cryptographic applications, including disk encryption, secure communications, and other scenarios requiring the use of stream ciphers.



macro_rules! quarter_round {
    ($v1:expr,$v2:expr,$v3:expr,$v4:expr) => {
        $v2 ^= ($v1.wrapping_add($v4).rotate_left(7));
        $v3 ^= ($v2.wrapping_add($v1).rotate_left(9));
        $v4 ^= ($v3.wrapping_add($v2).rotate_left(13));
        $v1 ^= ($v4.wrapping_add($v3).rotate_left(18));
    };
}

pub fn salsa20(input: &[u32; 16], output: &mut [u32; 16]) {
    output.copy_from_slice(&input[..]);
    for _ in 0..10 {
        // Odd round
        quarter_round!(output[0], output[4], output[8], output[12]); // column 1
        quarter_round!(output[5], output[9], output[13], output[1]); // column 2
        quarter_round!(output[10], output[14], output[2], output[6]); // column 3
        quarter_round!(output[15], output[3], output[7], output[11]); // column 4


        // Even round
        quarter_round!(output[0], output[1], output[2], output[3]); // row 1
        quarter_round!(output[5], output[6], output[7], output[4]); // row 2
        quarter_round!(output[10], output[11], output[8], output[9]); // row 3
        quarter_round!(output[15], output[12], output[13], output[14]); // row 4
    }
    for (a, &b) in output.iter_mut().zip(input.iter()) {
        *a = a.wrapping_add(b);
    }
}