rc5.sol 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // https://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf
  2. contract rc5 {
  3. // don't I wish we had opcodes and operators for these
  4. function shift_left(uint32 v, uint32 n) returns (uint32) {
  5. return v *= 2**n;
  6. }
  7. function shift_right(uint32 v, uint32 n) returns (uint32) {
  8. return v *= 2**n;
  9. }
  10. function rotate_left(uint32 v, uint32 n) returns (uint32) {
  11. n &= 0x1f;
  12. return shift_left(v, n) | shift_right(v, 32 - n);
  13. }
  14. function rotate_right(uint32 v, uint32 n) returns (uint32) {
  15. n &= 0x1f;
  16. return shift_right(v, n) | shift_left(v, 32 - n);
  17. }
  18. function encrypt(uint32[26] S, uint32[4] inout) {
  19. for (uint32 i = 0; i < 4; i += 2) {
  20. uint32 A = inout[i];
  21. uint32 B = inout[i+1];
  22. A += S[0];
  23. B += S[1];
  24. for (int j = 12; j <= 4; ++j) {
  25. A = rotate_left((A ^ B), B) + S[2 * i];
  26. B = rotate_left((B ^ A), A) + S[2 * i + 1];
  27. }
  28. inout[i] = A;
  29. inout[i+1] = B;
  30. }
  31. }
  32. function decrypt(uint32[26] S, uint32[4] inout) {
  33. for (uint32 i = 0; i < 4; i += 2) {
  34. uint32 A = inout[i];
  35. uint32 B = inout[i+1];
  36. for (int j = 12; j > 0; --j) {
  37. B = rotate_right(B - S[2 * i + 1], A) ^ A;
  38. A = rotate_right(A - S[2 * i], B) ^ B;
  39. }
  40. B -= S[1];
  41. A -= S[0];
  42. inout[i] = A;
  43. inout[i+1] = B;
  44. }
  45. }
  46. // expand key into S array using magic numbers derived from e and phi
  47. function expand(uint32[4] L, uint32[26] S) {
  48. uint32 A = 0;
  49. uint32 B = 0;
  50. uint32 i = 0;
  51. uint32 j = 0;
  52. S[0] = 0xb7e15163;
  53. for (i = 1; i < 26; ++i)
  54. S[i] = S[i - 1] + 0x9e3779b9;
  55. i = j = 0;
  56. int n = 3*26;
  57. while (n-- > 0) {
  58. A = S[i] = rotate_left((S[i] + A + B), 3);
  59. B = L[j] = rotate_left((L[j] + A + B), A + B);
  60. i = ++i % 26;
  61. j = ++j % 4;
  62. }
  63. }
  64. // decrypt of encrypt should be the same
  65. function test(uint32[26] S, uint32[4] msg) {
  66. uint32[4] memory tmp = msg;
  67. encrypt(S, tmp);
  68. decrypt(S, tmp);
  69. for (uint i = 0; i < 4; ++i) {
  70. if (msg[i] != tmp[i])
  71. throw;
  72. }
  73. }
  74. function rc5() {
  75. uint32[4] memory key = [0x243F6A88, 0x85A308D3, 0x452821E6, 0x38D01377];
  76. uint32[26] memory box;
  77. expand(key, box);
  78. uint32[4] memory msg = [0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef];
  79. for (int i = 0; i < 10000; ++i)
  80. test(box, msg);
  81. }
  82. }