Implement a CipherSaber encryption program, as described below. Guidelines:
- The smallest entry, in bytes, wins.
- However, in a departure from code-golf norms, you are welcome to post interesting entries, even if they aren't serious golf entries.
- An entry would typically be a program that takes the plaintext from standard input, and writes the ciphertext to standard output, with the key specified (by the user) in some way you prefer.
- However, if you wish to implement this as a procedure, that is fine too.
- The IV must come from a cryptographically secure pseudorandom number generator. If your language doesn't support that, choose a different one. ;-)
- Please do not use any crypto-specific libraries, system calls, or instructions (other than the PRNG, as stipulated above). Of course, generic low-level bitwise operations are okay.
CipherSaber is a variant of RC4/Arcfour, so I'll start by describing the latter, then the changes CipherSaber makes thereto.
0. RC4/Arcfour
Arcfour is fully specified elsewhere, but for completeness, I'll describe it here. (In case of any discrepancies between the Internet-draft and this description, the former is normative.)
Key setup
Set up two arrays, S
and S2
, both of length 256, where k_1
is the first byte of the key, and k_n
is the last.
S = [0, ..., 255]
S2 = [k_1, ..., k_n, k_1, ...]
(S2
is filled with the bytes of the key, again and again, until all 256 bytes are filled up.)
Then, initialise j
to 0, and shuffle 256 times:
j = 0
for i in (0 .. 255)
j = (j + S[i] + S2[i]) mod 256
swap S[i], S[j]
end
This completes key setup. The S2
array is no longer used here, and can be scrubbed.
Cipher stream generation
Initialise i
and j
to 0, then generate the key stream as follows:
i = 0
j = 0
while true
i = (i + 1) mod 256
j = (j + S[i]) mod 256
swap S[i], S[j]
k = (S[i] + S[j]) mod 256
yield S[k]
end
Encrypting/decrypting data
- To encrypt, XOR the keystream output with the plaintext
- To decrypt, XOR the keystream output with the ciphertext
1. CipherSaber
CipherSaber (which is what we're implementing in this question) is a variation of RC4/Arcfour in two ways:
10-byte IV/nonce
When encrypting a message, 10 random bytes should be obtained, such as via /dev/urandom
, and be written into the first 10 bytes of the encrypted output. When decrypting a message, the first 10 bytes of the input is the IV used to encrypt it.
The RC4/Arcfour key setup stage is run with passphrase || IV
as the key, where passphrase
is the user-specified passphrase, IV
is as described above, and ||
is concatenation. So, a passphrase of "Hello, world!" and an IV of "supercalif" (however unlikely that is :-P) would result in a key of "Hello, world!supercalif".
Multiple iterations of key setup
In order to help prevent the vulnerability that made WEP encryption completely broken, the shuffling loop of the key setup stage of RC4 is run a user-specified number of times. The value of j
should be retained between iterations.
2. Test vectors
Here are some test vectors you can use to test your programs. Furthermore, squeamish ossifrage created a CipherSaber encryption & decryption tool that you can use to validate your results.
You only need to implement the encryption program. You do not need to supply the decryption program, but your encryption program's output must roundtrip correctly to the original input when processed with a correctly-implemented decryption program using the correct key.