Skip to content

Instantly share code, notes, and snippets.

@allanlw
Created December 14, 2014 05:59
Show Gist options
  • Save allanlw/6fd37040bc8ae0275ba3 to your computer and use it in GitHub Desktop.
Save allanlw/6fd37040bc8ae0275ba3 to your computer and use it in GitHub Desktop.
RC4 PRNG unrolled with C++ templates
#include <cstdint>
#include <cstddef>
#include <cstdio>
#include <cstring>
struct RC4State {
uint8_t i, j;
uint8_t S[256];
RC4State(uint8_t *key, size_t key_len) : i(0), j(0) {
size_t i2;
uint8_t j2 = 0;
for (i2 = 0; i2 < 256; i2++) {
S[i2] = i2;
}
for (i2 = 0; i2 < 256; i2++) {
j2 += S[i2] + key[i2 % key_len];
Swap(i2, j2);
}
}
uint8_t GenerateOutput() {
i += 1;
j += S[i];
Swap(i, j);
return S[(S[i] + S[j]) % 256];
}
private:
void Swap(uint8_t i, uint8_t j) {
uint8_t temp = S[i];
S[i] = S[j];
S[j] = temp;
}
};
// Fill out with n successive PRNG outputs
// return the last one.
template <size_t n>
struct RC4Output {
static uint8_t generate(RC4State& s, uint8_t *out) {
RC4Output<n-1>::generate(s, out);
uint8_t K = s.GenerateOutput();
out[n-1] = K;
return K;
}
};
template <>
struct RC4Output<0> {
static uint8_t generate(RC4State& s, uint8_t *out) {
return 0;
}
};
int main(int argc, char **argv) {
if (argc != 2) {
puts("Supply one argument, key to use");
return 1;
}
RC4State s((unsigned char *)argv[1], strlen(argv[1]));
uint8_t output[256];
RC4Output<256>::generate(s, output);
for (int i = 0; i < 256; i++) {
printf("%02x", output[i]);
}
printf("\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment