TEA: Tiny Algorithm, Big Heart

Updated: August 20, 2026
cryptography python tiny-encryption-algorithm

This is an implementation of part of the Tiny Encryption Algorithm that I wrote in Python for a computer and network security class. The assignment had a narrow set of requirements: perform one pair of encryption rounds, show the intermediate values, and reverse them. I added input handling, tests, continuous integration, and a little extra functionality, then refactored it.

The code is public on GitHub.

This is teaching code. It performs two rounds so the arithmetic can be inspected; it is not a complete implementation of TEA and should not be used to encrypt anything important.

Diagram of the Tiny Encryption Algorithm's Feistel structure

Enough notation to follow it

TEA works on a 64-bit block split into two 32-bit halves, shown in the diagram as L0L_0 and R0R_0. Its 128-bit key is split into four 32-bit words, K0K_0 through K3K_3. One round leaves one half in place and uses it to change the other. The next round does the same thing from the other side.

The pair of round equations used by the assignment

There are only three operations to keep track of:

  • << and >> shift a 32-bit value left or right.
  • ^ is XOR. A bit in the result is 1 when the two input bits differ.
  • Addition modulo 2322^{32} is ordinary addition with anything beyond 32 bits discarded.

Hexadecimal is just a compact way to write the same bits. Four binary digits fit into one hexadecimal digit, so 10011111111101010111100111100101 becomes 0x9FF579E5. The 0x prefix says that the number is hexadecimal.

Python integers do not naturally wrap at 32 bits, so the implementation uses c_uint32 from ctypes. That makes additions and subtractions behave like unsigned 32-bit arithmetic.

Walking through two rounds

The first round copies R0R_0 into L1L_1. It also sends R0R_0 down three branches: shift left by 4 and add K0K_0; shift right by 5 and add K1K_1; add the first delta value. XOR those three results, add L0L_0, and the result is R1R_1.

The first round written out in Python

The second round starts from L1L_1 and R1R_1. It repeats the same structure with K2K_2, K3K_3, and the second delta value, producing L2L_2 and R2R_2.

The second round written out in Python

At that point the assignment calls the two 32-bit values ciphertext. Decryption does the same work in reverse. It reconstructs the three branches from the known half, XORs them, and subtracts instead of adding. Running both reverse steps recovers L0L_0 and R0R_0 exactly.

The final decryption step recovering the original block

The code is verbose on purpose. Each branch has its own named intermediate value because I was trying to grok the algorithm: to understand it closely enough that the notation stopped hiding the mechanism.

What the exercise proves

The tests run known inputs through encryption and decryption and check every intermediate value. At the time, the test report showed 96 percent coverage. Travis also ran Pylint, Flake8, coverage, Codecov, and SonarCloud on the repository.

Test coverage for the Python implementation

That proves the program implements the assignment consistently. It does not prove that the cipher is secure.

Full TEA normally runs 32 cycles, or 64 rounds, with a fixed delta derived from the golden ratio. This assignment used only one cycle and supplied its own two delta values so the calculation could be checked by hand. TEA also has known related-key and equivalent-key weaknesses; the equivalent keys reduce its effective key size from 128 to 126 bits. It is an unusually clear cipher to learn from, but there is no reason to choose it for a new system.

The value of the exercise was seeing that directly. Encryption and decryption were not black boxes anymore. They were a small sequence of shifts, XORs, and wrapping additions that could be followed in both directions, line by line.

Back to blog