-1

I'm in the process of implementing Three Fish block cipher using MATLAB. At first, I implemented the algorithm on uint8 numbers to validate my code. Every thing was OK and the decryption was successful. But when I replaced the numbers to uint64 the plain text did not retrieved correctly.
I traced the rounds results again and over again to find the reason, but I couldn't find it so far. There is difference in the first four digits between encryption and decryption, that is, along the rounds x encrypted as 9824265115183455531, but it decrypts as 9824265115183455488.

I think the reason behind this difference is in the functions AddMod64 and SubMod64 to find arithmetic modulo 2 to the power 64. but really I could not fix it so far.

I know that

    double(2^64) = 18446744073709552000

and

uint64(2^64) = 18446744073709551615 % z = ( x + y ) % 2^64
function z = AddMod64(x , y)
    m = uint64(2^64);
    z = double(mod(mod(double(x),m)+mod(double(y),m),m));
end
% z = (x - y ) % 2^64
function z = SubMod64(x , y)
    m = uint64(2^64);
    z = double(mod(mod(double(x),m) - mod(double(y),m),m)); 
end
user207421
  • 305,947
  • 44
  • 307
  • 483
Naseem
  • 39
  • 6
  • You should not be using floating point for cryptography. – user207421 Jul 28 '19 at 09:39
  • MATLAB does saturated arithmetic. If I does not use double, then mod(uint8(255+2),256) will be 255, while the correct result must be 1 – Naseem Jul 28 '19 at 10:35
  • `double(2^64)` is already the wrong result, the `double` type can hold only up to `2^52-1` as an integer without rounding. Use `maxint` instead. – Cris Luengo Jul 28 '19 at 13:36

1 Answers1

2

double(2^64) is already the wrong result, the double type can hold only up to 2^52-1 as an integer without rounding.

Also, when you do uint64(2^64), the power is computed using double, giving the wrong result, which you then cast to uint64. And because the maximum value that a uint64 van hold is 2^64-1, that whole operation is wrong.

Use maxint instead:

m = maxint('uint64');

To do modulo addition in MATLAB is rather tricky, because MATLAB does saturated arithmetic with integers. You need to test for overflow before doing the computation.

if x > m - y
   x = y - (m - x + 1);
else
   x = x + y
end
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
  • intmax('uint64') = uint64(2^64) = 18446744073709551615 – Naseem Jul 28 '19 at 14:53
  • Before writing the code, I had computationally traced the Three Fish block cipher key scheduling and encryption by hand on uint8 numbers. When I wrote the code, at first, I tested for overflow before doing the modulo addition (as you mentioned). But My code (AddMod8 function, which operate on uint8) has matched the paper result more than the code you mentioned – Naseem Jul 28 '19 at 15:36
  • Note that `intmax('uint64')` is 2^64-1. That your two operations return the same value is a combination of luck (the double computation is not rounded down) and saturation in the conversion to `uint64`. – Cris Luengo Jul 28 '19 at 16:36
  • Also, if your saturated addition for 8 bits gives a different result to the mod version for 8 bits then you did something wrong. For 64 bits you cannot use the mod function, doubles cannot hold a 64-but integer without loss. – Cris Luengo Jul 28 '19 at 16:53