Instantly share code, notes, and snippets.

Created October 21, 2017 01:48
Show Gist options
• Save gcolvin/7a0f251f71b7f46251d3400add8fd703 to your computer and use it in GitHub Desktop.
rc5.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 // https://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf #include #include #include uint32_t shift_left(uint32_t v, uint32_t n) { return v << n; // return v * pow(2, n); } uint32_t shift_right(uint32_t v, uint32_t n) { return v >> n; // return v / pow(2, n); } uint32_t rotate_left(uint32_t v, uint32_t n) { n &= 0x1f; return shift_left(v, n) | shift_right(v, 32 - n); } uint32_t rotate_right(uint32_t v, uint32_t n) { n &= 0x1f; return shift_right(v, n) | shift_left(v, 32 - n); } void encrypt(uint32_t S[26], uint32_t inout[4]) { for (uint32_t i = 0; i < 4; i += 2) { uint32_t A = inout[i]; uint32_t B = inout[i+1]; A += S[0]; B += S[1]; for (int j = 0; j < 12; ++j) { A = rotate_left((A ^ B), B) + S[2 * i]; B = rotate_left((B ^ A), A) + S[2 * i + 1]; } inout[i] = A; inout[i+1] = B; } } void decrypt(uint32_t S[26], uint32_t inout[4]) { for (uint32_t i = 0; i < 4; i += 2) { uint32_t A = inout[i]; uint32_t B = inout[i+1]; for (int j = 12; j > 0; --j) { B = rotate_right(B - S[2 * i + 1], A) ^ A; A = rotate_right(A - S[2 * i], 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 void expand(uint32_t L[4], uint32_t S[26]) { uint32_t A = 0; uint32_t B = 0; uint32_t i = 0; uint32_t 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 + 1) % 26; j = (j + 1) % 4; } } // decrypt of encrypt should be the same int test(uint32_t S[26], uint32_t messg[4]) { uint32_t save[4]; memcpy(save, messg, sizeof save); encrypt(S, messg); decrypt(S, messg); for (int i = 0; i < 4; ++i) { if (messg[i] != save[i]) return 0; } return 1; } int main() { uint32_t key[4] = { 0x243F6A88, 0x85A308D3, 0x452821E6, 0x38D01377 }; uint32_t box[26]; expand(key, box); uint32_t message[4] = { 0xfeedface, 0xdeadbeef, 0xfeedbabe, 0xcafebeef }; for (int i = 0; i < 43690; ++i) if (!test(box, message)) return 1; return 0; }

### jinhaichen commented Dec 24, 2019

In Line 33

```		for (int j = 0; j < 12; ++j) {
A = rotate_left((A ^ B), B) + S[2 * i];
B = rotate_left((B ^ A), A) + S[2 * i + 1];
}```

I think the correct code is

```		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];
}```

The decryption process is also wrong

### gcolvin commented Dec 24, 2019

Thanks @scnucjh, you are right. If you want to make a PR that would be great, otherwise I'll get to it when I can.

### gcolvin commented Dec 27, 2019

Hi @scnucjh

Fixed, I hope, in the original repo.

https://github.com/gcolvin/evm-drag-race/blob/master/rc5.sol