Perror already covered this particular case, but here are some general principles for inverting similar functions.
Note: all of this assumes the integer is either unsigned, or it is signed using two's complement and using unsigned shifts. In Java, two's complement is guaranteed. In C/C++, it is not guaranteed, but it's almost always the case in practice, and you can check the compiled assembly to be sure.
A sequence of transformations involving xor and bitshifts can be thought of as a linear (or affine if there are constants) transformation on a vector in (GF2)^32. Essentially, you have a 32 element vector of numbers mod 2, and since xor is addition mod 2, and you are multiplying it by a matrix.
So the transformation is invertible iff the matrix is invertible. Luckily this is usually the case. A function of the form x ^ (x >>> n)
with n > 0 is a lower triangular matrix and hence invertible. Likewise, x ^ (x << n)
is an upper triangular matrix and so also invertible. Since the product of invertible matrices is invertible, any sequence of such transformations will also be invertible.
Note that a signed shift (>> in Java) is not necessarily invertible.
As for actually inverting it, the easiest way (though not necessary the fastest) is to simply calculate the transformation matrix entries, then perform Guassian elimination (no rounding errors in a finite field).
You'll often see other operations mixed in as well. Addition and multiplication can be thought of as operations in the ring modulo 2^32. With two's complement, it doesn't matter whether you're using signed or unsigned numbers. Addition by a constant is simple: just subtract the constant. Multiplication by any odd constant is also invertible: just multiply by the multiplicative modular inverse. You can find code to calculate this online, or just take pow(c, (2**31)-1, 2**32)
if you're doing Python.
Multiplication by an even constant loses information, so it cannot be fully inverted. Likewise, a combination of additions with the same effect won't be either. For example x + x
is not invertible, since it's equivalent to x * 2
. x + (x<<4)
is invertible, because it is equivalent to x * 17
.
Due to the fact that the composition of affine transformation is also affine, you can save time by just multiplying through all such operations and then inverting it in a single step.
Bitwise ands and ors always lose information except in the trivial case, so they won't be invertible. But usually they are used to select part of the information for combination in a lossless manner, so the overall expression is still invertible. For example x ^ ((x & 555) * 4)
is invertible even though two of the individual components of the expression are noninvertible operations.
A couple other things you might see. Operations in GF(2^32) are basically the same as regular addition and multiplication except there's no carry. This is typically used in CRCs. Addition (which is just xor) and multiplication by any nonzero number are invertible, using the same technique as before.
Substitution boxes (or sboxes) - these are designed to be invertible, but normally don't have any particular structure. Typically these are expressed as a table lookup, with a precomputed table for the inverse as well. If not, you can always make your own inverse table, assuming the inputs aren't too big.
y
space is limited (4 byte int) you can do an exhaustive search on f(y)