-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrc4.c
114 lines (89 loc) · 2.08 KB
/
rc4.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rc4.h"
/* Initalize the RC4 state @ctx with @key of length @klen */
void rc4_init_key(struct rc4_ctx *ctx, unsigned char *key, size_t klen)
{
int i;
for(i = 0; i < 256; i++)
ctx->S[i] = i;
rc4_shuffle_key(ctx, key, klen);
}
/* Second half of the key-init algorithm, used to preserve state from
* last call (ctx doesn't get filled 1-256 in order)
*/
void rc4_shuffle_key(struct rc4_ctx *ctx, unsigned char *k, size_t l)
{
int i;
unsigned char tmp, j = 0;
for(i = 0; i < 256; i++) {
j = (j + ctx->S[i] + k[i % l]) & 255;
tmp = ctx->S[i];
ctx->S[i] = ctx->S[j];
ctx->S[j] = tmp;
}
}
/* Write @nb bytes of RC4 keystream to @buf from cipher context @ctx */
void rc4_fill_buf(struct rc4_ctx *ctx, unsigned char *buf, size_t nb)
{
unsigned char i, j, k, idx, tmp;
unsigned char *state = ctx->S;
size_t n = 0;
i = j = k = 0;
do
{
i = (i + 1) & 255;
j = (j + state[i]) & 255;
tmp = state[i];
state[i] = state[j];
state[j] = tmp;
idx = (state[i] + state[j]) & 255;
*(buf + n) = state[idx];
} while(++n < nb);
}
/* XOR a buffer with the keystream */
void rc4_xor_stream(struct rc4_ctx *ctx, unsigned char *buf, size_t n)
{
unsigned char i, j, k, tmp;
unsigned char *state = ctx->S;
size_t ctr = 0;
i = j = k = 0;
do
{
i = (i + 1) & 255;
j = (j + state[i]) & 255;
tmp = state[i];
state[i] = state[j];
state[j] = tmp;
*(buf + ctr) ^= state[(state[i] + state[j]) & 255];
} while(++ctr < n);
}
/* Copy an existing rc4 context */
struct rc4_ctx *rc4_copy_ctx(struct rc4_ctx *src)
{
struct rc4_ctx *new_ctx = malloc(sizeof(struct rc4_ctx));
if (new_ctx == NULL)
return NULL;
memcpy(new_ctx, src, sizeof(struct rc4_ctx));
return new_ctx;
}
#ifdef TEST
#include <string.h>
int main(int argc, char *argv[])
{
struct rc4_ctx ctx;
char buf[1024];
int n = 456;
if(argc < 2) {
puts("Error, requires key argument\n");
return 1;
}
rc4_init_key(&ctx, argv[1], strlen(argv[1]));
while(n--) {
rc4_fill_buf(&ctx, buf, 1024);
fwrite(buf, 1024, 1, stdout);
}
return 0;
}
#endif