JavaScript numbers

Javascript uses IEEE 754 for the representation of numbers, which are 64 bit double precision floating point numbers, which are exact for integers up to 53 bits. Javascript performs the common arithmetic operations such as addition and multiplication in sufficient precision, i.e., 53 bits when no overflow occurs. However, Javascript performs certain bit-wise operations (such as XOR '^', SHIFT '<<', etcetera) in 32 bit precision. The results of such operations are sign-extended (at least they are in Firefox/Linux and InternetExplorer/WinXP). That is, if the result of such a 32-bit operation in an environment where a 64-bit value is required has bit 31 set to 1, the result is extended to a negative number, and otherwise to a positive number.

This situation may lead to unexpected results. For instance, the value of (1<<31)+2*(1<<30) is computed by your browser as 0, which may be unexpected because it is the sum of two large positive numbers. More surprising is that both these numbers are expressible in 32 bits.

The reason for this idiosyncrasy is that 1<<31 has bit 1 set, and is therefore extended to a negative number (-2147483648). In this case precisely minus 2*(1<<30). Subsequent addition leads to erors that permeate within the lower 32 bits.

Unfortunately the TEA algorithm is a mesh of bit-wise and ordinary arithmetic operations by intention. For instance, the algorithm contains a statement such as y += ((z << 4) ^ (z >> 5)) + (z ^ sum) + k[sum&3];. That statement is bound to produce erroneous results in JavaScript, so the two implementations mentioned in Simon Shepherd's site are flawed (http://www.simonshepherd.supanet.com/tea_js.htm and http://www.simonshepherd.supanet.com/jstea.htm).

This may seem not so bad as all: encryption and decryption are inverse functions so as long as the flaw is symmetric, i.e., is reversed when a function's reverse is used, everything is ok. This seems to be the case in the mentioned implementations, because they are able to decrypt their encrypted data.

Two problems remain:

  • When the algorithm is used in agent-communication, where agents use different implementations (such as JavaScript-PHP client-server communication) decryption no longer works, asuming the second language doesn't exhibit the same behavior;
  • Perhaps more importantly, the desirable theoretic properties of TEA, diffusion and confusion, are reduced by this flaw. This implementation is theoretically less secure.
The solution shown here sets the result of every 32-bit operation to the appropriate positive value. The JavaScript and PHP implementations are compatible and can decrypt each others data.

PHP

Note that the PHP implementation also truncates values at 32 bits. This is necessary to mimic 32-bit unsigned arithmetic. It is required because the algorithm right-shifts bits that are more significant than bit 32 back the least-significant bits.
Built with Bloom