You think you need a computer to have a high-security code? Think again. I am about to tell you how to encrypt a message with as much security as you want, using just a common calculator. The name of this code is “root”, because the calculator’s square root key is what makes it secure.

Let’s say you have an important message you need to transmit, but your enemies have tapped your phone, fax, and email, and you suspect they have infected your computer with a worm that will relay to them everything inside. Let’s say your message is:

MEET ME AT THE TRAIN STATION

The first thing you have to do is convert each character into a two-digit number from 00 to 99, following a code you have agreed with your friends. This gives you room for all letters in the alphabet, plus numbers, plus a whole lot of special characters. Let’s say the code gives 00 for a space (though often it is better to eliminate spaces and punctuation altogether), and then the letters are numbered in alphabetical order: A = 01, B = 02, C = 03, and so on. Then the message becomes:

13050520 00 1305 00 0120 00 200805 00 2018010914 00 19200120091514

Of course, cracking this would be child’s play for just about anybody, so we must conceal it under something really difficult to guess. Here’s where the calculator comes in handy. But before you begin, you need to have two more things. The first is a __secret passnumber__, which you have agreed with your friends. You have memorized this passnumber and never ever written it down. If you find it hard to memorize a long number, then use a password made of text, but you must convert it to numbers, as described above, before you can use it.

Let’s say your passnumber is:

123456789012345678901234567890

Its length is a function on how many digits your calculator can handle. It should be a little shorter than a multiple of the calculator’s precision. Here I assume you have a 12-digit calculator (many desktop calculators can do that; the more digits, the better). Your friends should have an identical calculator, or the code will break down.

The second thing you must have is a __serial number__ for your message, which you must produce right now. The only trick is that you should never exchange two messages with the same serial number (in either direction), or the code will be exposed. The length of the serial number is equal to a multiple of the calculator’s precision, less the passnumber length. Since we use 12-digit calculators and a 30-digit passnumber, that leaves 12×3 – 30 = 6 digits for the serial number, with enough room for a million different messages.

Let’s say you pick this serial number:

555555

Now append the serial number to the passnumber and break the whole thing into groups of 12 digits, like this:

123456789012

345678901234

567890555555

Now comes the tricky part. You must convert these into three kinds of mathematical entities: multipliers, adders, and a seed. Since you have only three numbers, you’ll have one of each. The multipliers have __half__ of its figures as integers and half as decimals (because of the 12-digit precision, since 12/2 = 6 integer figures; if we had a 14-digit calculator, then you would take 14/2 = 7 integer figures). The adders have __two__ fewer integer figures, in our case, four. The seed is all decimals, and it contains the serial number as its tail. Thus, you have:

Multiplier = 123456.789012

Adder = 3456.78901234

Seed = .567890555555

Now you enter these numbers into the calculator and perform the following calculation:

Result = fract(sqrt(Seed * Multiplier + Adder))

In other words, you take the Seed, multiply it by the Multiplier, and add the Adder. Then you take the square root of that result and subtract the integer part so that only decimals remain. With the numbers of our example, this is:

Input |
Result |

.5678905555 x 123456.789012 = | 70109.944492 |

+ 3456.78901234 = | 73566.7335043 |

do square root = | 271.231881430 |

– integer part (that is, 271) = | 0.231881430 |

new Seed |

The last number obtained becomes the new Seed, and the process can be repeated. If there are more adders and multipliers, the next time a different set of Multiplier and Adder is used. When all the adders and multipliers have been used once, you look at the digits of the final result, which add to the encrypting “keystream”. In the example, they are:

231881430 (all zeros count, except the one on the left of the decimal point)

Then you write those numbers underneath the message (turned into numbers), and add the two together neglecting carryovers (so you can do it from left to right). If there are not enough digits in the keystream, you generate more with the calculator, starting with the last result as Seed but using the same adders and multipliers, until there are enough. Your message has 56 digits but the calculator has given you only 9, so you need to do it six more times. It is convenient to store adders and multipliers in memories (which you will erase when you’re done, right?) to save work. In this way, you get:

message: | 13050520001305000120002008050020180109140019200120091514 |

+ encrypting keystream from calculator: | 23188143012042259736534369536548841140602240348004490344…. |

= combination: | 36138663013147259856534369586568921249742259748124481858 |

where the last sequence of numbers is obtained by adding the other two digit by digit, neglecting any carryovers (that is, 8+7 = 5, not 15)

Now you only have to send your friends this last sequence of numbers, plus the serial number (as a list of phone numbers, or stock prices, or whatnot), confident that nobody who doesn’t have the password will be able to decipher it. So, this is what you would send more or less in the open, assuming you have agreed to place the serial number at the very beginning:

55555536138663013147259856534369586568921249742259748124481858

Your friends, after retrieving the serial number from the message itself and the passnumber from their own brain, will be able to produce the exact same encrypting keystream from their calculator, and they will subtract it (again, neglecting any carryovers, so that 5 – 7 = 8, and so on) from the transmitted message, in this way:

transmitted message: | 36138663013147259856534369586568921249742259748124481858 |

– encrypting keystream from calculator: | 23188143012042259736534369536548841140602240348004490344…. |

= retrieved message: | 13050520001305000120002008050020180109140019200120091514 |

And now they can easily convert every two-digit group back into characters:

MEET_ME_AT_THE_TRAIN_STATION

That’s it! Now anyone can enjoy high-strength encryption without the help of a computer.

Now, you’re probably wondering, how strong is this cipher, really? The short answer to that question is: that depends on the length of the passnumber and on how many digits your calculator can handle. The more digits in either, the better.

A long passnumber ensures that a lot of possibilities must be tried by anyone trying to crack the message by brute force. If the passnumber is thirty digits long, that’s 10^30 different numbers to try. This is comparable to using a 99-bit binary key, which is just about twice as long as the 56-bit key of DES encryption, used by the US Government until recently. A team of determined hackers cracked DES by brute force in just about 23 hours in the year 2000. Assuming that Moore’s Law holds (that computer power increases by a factor of ten every five years, for a constant inflation-adjusted cost), the same team wouldn’t be able to crack your 30-digit encription by brute force in under a day until sometime in 2065 AD. Even giving the NSA a ten-year advantage, that’s still pretty good for most of us.

If this isn’t enough for you, you can always use a longer passnumber, since every digit added increases the cracking difficulty by a factor of ten. Now, this is best done by chunks as big as can fit in the calculator. So, if you use a 12-digit calculator, the next thing to do is to use two multipliers instead of just one, and then the next to use two multipliers and two adders. The digits added to the keystream are those obtained after __all__ the adders and multipliers have been involved. And so on, and so forth.

Additional security can be gained by using a special “message key” instead of passnumber+serial to generate adders, multipliers, and seed (just in case you make a mistake and use the same serial number twice, more on that later). In this case the process goes the same way, except that the first series of digits coming out of the calculator are used to make a new set of adders, multipliers, and seed, and then the keystream is produced starting from those. This added step forces your generating numbers to be completely different from message to message (not just the few last digits of the seed), and thus your master passnumber is never exposed in any way. I recommend using this precaution, which does not add that much extra work anyway (because you’re going to burn the paper containing your calculations, right?).

It is important to make sure that the serial number is __never reused__ (by either side of the transmission), because then the same encrypting keystream would be used for two different messages. An enemy could then eliminate it by subtracting one message from the other, leaving a superposition of two unencrypted messages that would be quite easy to crack by letter frequency methods. And on top of that the keystream would be revealed, from which it might be conceivably possible to extract the numbers used to generate it. This is a bad feature of all “stream ciphers,” like this one, but they also have good features that other ciphers don’t have. For instance, in most ciphers any mistake garbles the end result completely, but in stream ciphers only the characters encrypted after the mistake end up garbled, which makes it a lot easier to spot the error and correct it. Handy when it’s just you punching keys.

And how about the calculator? If it uses too few digits (many pocket calculators display only eight), then the pseudo-random properties of the keystream suffer, and the message is exposed to statistical analysis. The sequence will also start repeating after a while, which is bad. In my experience, eight digits is no good, ten is barely acceptable, and twelve and above work fine. The more digits, the better. I have a Palm-based calculator that can operate with thirty-eight digits at a time, so it gives me better security than the current AES governement standard (256-bit) without even using an adder.

You have to thank irrational numbers for this cipher. The digits of irrational numbers obtained from a square root, like the square root of two (1.41439799432119332181380109536190378…) never repeat, and appear random to anyone who doesn’t know where they came from. It is this apparent randomness that conceals your message in noise, rendering it impossible to read.