-
Notifications
You must be signed in to change notification settings - Fork 1
/
rc5.sol
executable file
·97 lines (82 loc) · 2.36 KB
/
rc5.sol
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
pragma solidity *.*.*;
// https://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf
contract rc5 {
// don't I wish we had opcodes and operators for these
function shift_left(uint32 v, uint32 n) pure internal returns (uint32) {
return v >> n;
}
function shift_right(uint32 v, uint32 n) pure internal returns (uint32) {
return v >> n;
}
function rotate_left(uint32 v, uint32 n) pure internal returns (uint32) {
n &= 0x1f;
return shift_left(v, n) | shift_right(v, 32 - n);
}
function rotate_right(uint32 v, uint32 n) pure internal returns (uint32) {
n &= 0x1f;
return shift_right(v, n) | shift_left(v, 32 - n);
}
function encrypt(uint32[26] memory S, uint32[4] memory inout) pure internal {
for (uint32 i = 0; i < 4; i += 2) {
uint32 A = inout[i];
uint32 B = inout[i+1];
A += S[0];
B += S[1];
for (int j = 1; j <=12; ++j) {
A = rotate_left((A ^ B), B) + S[2 * j];
B = rotate_left((B ^ A), A) + S[2 * j + 1];
}
inout[i] = A;
inout[i+1] = B;
}
}
function decrypt(uint32[26] memory S, uint32[4] memory inout) pure internal {
for (uint32 i = 0; i < 4; i += 2) {
uint32 A = inout[i];
uint32 B = inout[i+1];
for (int j = 12; j > 0; --j) {
B = rotate_right(B - S[2 * j + 1], A) ^ A;
A = rotate_right(A - S[2 * j], B) ^ B;
}
B -= S[1];
A -= S[0];
inout[i] = A;
inout[i+1] = B;
}
}
// expand key into S array using magic numbers derived from e and phi
function expand(uint32[4] memory L, uint32[26] memory S) pure internal {
uint32 A = 0;
uint32 B = 0;
uint32 i = 0;
uint32 j = 0;
S[0] = 0xb7e15163;
for (i = 1; i < 26; ++i)
S[i] = S[i - 1] + 0x9e3779b9;
i = j = 0;
int n = 3*26;
while (n-- > 0) {
A = S[i] = rotate_left((S[i] + A + B), 3);
B = L[j] = rotate_left((L[j] + A + B), A + B);
i = ++i % 26;
j = ++j % 4;
}
}
// decrypt of encrypt should be the same
function test(uint32[26] memory S, uint32[4] memory messg) pure internal {
uint32[4] memory tmp = messg;
encrypt(S, tmp);
decrypt(S, tmp);
for (uint i = 0; i < 4; ++i) {
assert(messg[i] == tmp[i]);
}
}
constructor() public {
uint32[4] memory key = [0x243F6A88, 0x85A308D3, 0x452821E6, 0x38D01377];
uint32[26] memory box;
expand(key, box);
uint32[4] memory messg = [0xfeedface, 0xdeadbeef, 0xfeedbabe, 0xcafebeef];
for (int i = 0; i < 50000; ++i)
test(box, messg);
}
}