Skip to content

Instantly share code, notes, and snippets.

@gcolvin
Created October 21, 2017 01:48
Show Gist options
  • Save gcolvin/7a0f251f71b7f46251d3400add8fd703 to your computer and use it in GitHub Desktop.
Save gcolvin/7a0f251f71b7f46251d3400add8fd703 to your computer and use it in GitHub Desktop.
rc5.c
// https://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf
#include <stdint.h>
#include <string.h>
#include <math.h>
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
Copy link

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
Copy link
Author

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
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment