Salsa20 Cipher - Rust
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.
- Key Expansion:
- Salsa20 takes a 256-bit key and a 64-bit nonce (number used once) as input.
- The key and nonce are expanded using a series of bitwise operations and additions to create a 512-bit internal state.
- The expanded key is used to generate a stream of pseudorandom numbers.
2. Pseudorandom Number Generation:
- Salsa20 uses a quarter-round function applied repeatedly to its internal state to generate pseudorandom numbers.
- The quarter-round function involves various bitwise operations such as addition (XOR) and rotation.
- The function is applied 20 times in Salsa20/20 and 12 times in Salsa20/12, hence the names.
3. Stream Generation:
- 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).
- This XOR operation creates the keystream, which is then combined with the input data to produce the output.
4. Block Size and Counter:
- Salsa20 operates on 64-byte (512-bit) blocks.
- 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.
- The block counter is incremented for each block processed.
5. Security:
- Salsa20 is considered secure and has withstood extensive cryptanalysis.
- It provides a high level of security with a relatively simple and efficient design.
6. Usage:
- 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);
}
}