3 ms·
For folks confused that the blog post doesn't just say "2^INT_BITS factorial", I think the idea is that you want efficient reversible operations on modern CPUs.
by twotwotwo 9y ago
For folks confused that the blog post doesn't just say "2^INT_BITS factorial", I think the idea is that you want efficient reversible operations on modern CPUs. These can be useful in, for example, cryptography and non-cryptographic checksums and RNGs. Even if you don't actually ever run the inverse function, using an invertible op ensures that no information from the input is dropped and every output is possible. Of course, you also need the invertible function to have whatever other properties you want for your particular use, like diffusion or nonlinearity. The XOR-three-rotations operation, for example, is used in the "sigma" functions providing diffusion in SHA-2, though you never use the inverse.
With a block of >1 integer, there are some additional fun ones:
- XOR an even number of integers together, then XOR the resulting value, or any function of it, into all of them. (It's its own inverse, since the XOR of an even number integers isn't changed by XORing the same value into all of them.)
- Bitslicing S-boxes, a potentially nonlinear operation. You can represent S-boxes (esp. small ones) as a network of gates, and you can turn those into AND/OR/XOR/NOT instructions and have your CPU do them on registers at a time. This was core to the AES candidate Serpent using 32-bit registers; now you have larger regs to do it with.
- Some matrix multiplications (including in fields). Thinking of AES's use of MDS matrices.
- Generalized Feistel-like operations: run some function--not necessarily reversible--on part of the input, and use the result to munge another part of the input. a ^= f(b) or (some of the generalizations) a += f(b) or a ^= f(b, c, d). Used tons of places, of course. Then you can easily build an invertible function (on the larger block) from a non-invertible round function, and repeat for a zillion rounds (a ^= f(b, k1); b ^= f(a, k2); a ^= f(b, k3)...). With a loose enough definition of "Feistel-like", even lots of ARX ciphers could qualify.
(You could, of course, do some of these things within a single integer by thinking of it as two, four, etc. narrower ints, or you could call a whole block a very large int. Mostly thinking of register-sized integers when I say integers, FWIW.)
Keccak (SHA-3) has some steps where, like with the XOR-three-rotatations thing, an inverse exists but looks a bit different from the original operation, which is neat! There's a reference (https://keccak.team/files/Keccak-reference-3.0.pdf https://keccak.team/files/Keccak-reference-3.0.pdf) describing the operations using math notation, and lots of C implementations (https://github.com/rhash/RHash/blob/master/librhash/sha3.c https://github.com/rhash/RHash/blob/master/librhash/sha3.c). It looks like the team published code for the inverses too; see https://github.com/gvanas/KeccakTools/blob/master/Sources/Keccak-f.h https://github.com/gvanas/KeccakTools/blob/master/Sources/Ke...