By the look of it, the decoder function requires the input to be a multiple of 4 characters and uses a modulus operation on a negative number to know how many equal signs to add to make that true. Modulus operations involving negative numbers work differently in different languages. That’s probably what’s wrong.
The modulus operator, for those who do not know, returns the remainder of a division and is written using the percent sign when writing code. 5 % 3 = 2
because 3 fits into 5 once with 2 left over.
The following code obtains the length of the payload using a len()
function, flips its sign so that it is negative, and then does a modulus division by 4. The result of this operation is how many equal signs are padded onto the payload to hopefully make it an even multiple of 4.
(-len(payload) % 4)
In python, lengths of 4, 5, 6, and 7 would return results of 0, 3, 2, and 1 because in python taking the modulus of a negative number returns the inverse remainder.
5 % 3 = 2
, but -5 % 3 = 1
Results:
4 + 0 = 4
5 + 3 = 8
6 + 2 = 8
7 + 1 = 8
All of these are totals neatly divisible by 4.
In PHP, lengths of 4, 5, 6, and 7 would return 0, 1, 2, and 3 because the negative sign is ignored.
Results:
4 + 0 = 4
5 + 1 = 6
6 + 2 = 8
7 + 3 = 10
Adding these together produces a result divisible by 4 only half the time. That’s bad ju ju, and why trying to copy this exactly from python to PHP would not work as expected.
This article contains more information: