**Note: This page requires a MathML-capable browser to
display properly. If the symbol in brackets ($\u27f6$) isn't an arrow, please use the HTML version instead.**

In this article, I discuss methods for encrypting messages, with particular emphasis on the code known as RSA. The background material on congruences, Euclid's algorithm, etc. is also discussed. The material presented should by accessible to a mathematics or theoretically-oriented science undergraduate, or to a bright A-level student. Terms which may seem technical appear in italics.

- Introduction
- The Maths behind the Code
- Implementing the Code
- A Java Implementation of the RSA Code
- Congruences and Euclid's Algorithm
- Notes for Nerds (aka Technical Notes)
- Links
- About this Document

The RSA code is an 'unbreakable' cipher - a means of
scrambling a message so that it will be indecipherable to prying
eyes. In mathematical terms, a cipher is a special kind of
mapping from an set A, called the *alphabet* (not
necessarily a natural alphabet!), to itself. The mapping must be
a *bijection*, i.e. it must be *invertible*,
because we would like to be able to recover the original message
given the encoded message.

One of the oldest ciphers was used by Julius Caesar and
involves permuting the letters of the alphabet, often simply shifting
each letter a fixed number of places. For instance, if we agreed to
shift every letter 3
places down, then the letter 'B' would become 'E', 'G' would
become 'J' and so on. The phrase 'fifth legion advance' would
become 'iliwk ohjlrq dgydqfh'. To get back the original message,
all we have to do is to transpose each letter 3 places up in the
alphabet. In a code such as the Caesarian, which is really a
collection of similar codes that depend on a parameter (in this
case the number of places by which each letter is shifted), the
parameter is called the *encryption key*

There are a number of problems with Caesar's method. Because
we are using the ordinary Roman alphabet, there are only
$26!=4.0329\times {10}^{26}$
different possible codes (the total number of *permutations*
on a set of size 26), this might seem like a big number, but
modern computers can search through all the possiblities in a
relatively small amount of time. (moreover, if we insist on using
simple shifts, then there are only 26 different possibilities,
one of which is clearly useless!) Another problem, of a more
practical nature, is how Caesar is going to let his generals know
of the encryption key.

The RSA code addresses both problems. On the one hand, it allows the use of alphabets of arbitrary length, but, more fundamentally, the main advantage of the RSA code is that even if the encryption method should fall into enemy hands, it is still very difficult to invert the cipher. For this reason, the RSA code is sometimes known as public-key encryption, because the encryption key can be divulged to everyone without posing a security risk.

Before explaining how to encode a natural message, I will discuss how the RSA code works on a special alphabet of numbers. But we'll need to define a few mathematical terms along the way.

**Definitions****
(see below for examples!)**

- Let a and c be whole numbers. We say that c
*divides*a if there exists a whole number d such that a = c d. - A whole number p is said to be prime if the only divisors of p are 1 and p.
- Let a and b be whole numbers. The
*highest common factor*of a and b ( written hcf(a,b) ) is any whole number, d , such that d divides a, d divides b; and if c is whole number such that c divides a and c divides b then c divides d. ( or, put another way, d is a 'common factor' of a and b, moreover, d is the 'highest' of the common factors. ) - Let a and n be whole numbers. We say that a is
*coprime*to n ( or that a is*relatively prime*to n ) if hcf(a,n) = 1. - Let n be a positve whole number. Define the set R(n) to be the whole numbers between 0 and n - 1 which are coprime to n. ( Note: this is non-standard notation )
- Let n be a positive whole number. We define the
*Euler phi function*, $\phi $(n) = the size of R(n).

**Examples**

- 5 divides 10. The number 2 divides any even number. Any whole number divides 0.
- The highest common factor of 24 and 16 is 4. hcf(10,7) = 1. hcf(p,n) = 1 if p is a prime number and n is not a multiple of p. hcf(n,0) = n for any whole number n.
- 10 is coprime to 7.
- If n = 10 then R(n) = {1, 3, 7, 9 }. If n = 21 then R(n) = { 1, 2, 4, 5, 8, 10, 11, 13, 16, 17, 19, 20 }. If n is a prime number then R(n) = { 1, 2, 3, 4, ..., n-1 }
- $\phi $(10) = 4. $\phi $(21) = 12. If n is a prime number then $\phi $(n) = n-1.

The following Java applet calculates the hcf of any two whole numbers and expresses the hcf as a linear combination of the numbers:

Choose any (largish!) positive whole number n. **The set
of elements which we will encode in the RSA scheme is simply R(n)**.
This takes the place of the Roman alphabet in Caesar's code.

Look back at Caesar's code. What is really going on is that there is a bijection f : A $\u27f6$ A (where A is the Roman alphabet ) which tells us to shift each letter a certain number of places. We are going to find a bijection f : R(n) $\u27f6$ R(n) which is relatively easy to carry out, but very hard to invert. This will be our code.

First we need a little theorem about congruences. If you've never heard of these objects, follow the link in the previous sentence.

**Lemma**

Let n be a positive whole number and t a whole number such that t $\equiv $ 1 mod $\phi $(10) = 4. $\phi $(n). If x is coprime to n, then ${x}^{t}\equiv x\mathrm{mod}n$ . The proof is left as an easy exercise (easy iff you know the Fermat-Euler theorem).

**Corollary**

If e is positive integer such that e is coprime to $\phi $(10) = 4. $\phi $(n) then the map f : R(n) $\u27f6$R(n) defined by $f\left(x\right)={x}^{e}$ is a bijection (i.e. is invertible).

**Proof**

We'll use the above lemma to find an inverse. The idea is to
find a whole number d such that if t = ed then t $\equiv $
1 mod $\phi $(10) = 4. $\phi $(n).
Then for any x in R(n),
$x={x}^{t}={x}^{ed}={\left({x}^{e}\right)}^{d}$.
That is, the
mapping g : R(n) $\u27f6$R(n)
defined by
$g\left(y\right)={y}^{d}$,
is the required inverse for f. But such a d
**does** exist, because e is coprime to $\phi $(10) = 4. $\phi $(n) (
see the section on congruences ). QED.

So now we have our bijection ( namely the function f introduced in the corollary ). Why is it difficult to invert? If we are to use the method of the corollary to find an inverse function, we first need to calculate $\phi $(10) = 4. $\phi $(n). The best method known for evaluating $\phi $(10) = 4. $\phi $(n) requires factorising n ( i.e. writing n as a product of its factors ). In general, for large n ( say 100 digits or more ), this is a tough problem, particularly if n has only a small number of factors. Often n is chosen to be the product of two large prime numbers. Of course, there may be an alternative method for finding the inverse function ( without needing to calculate $\phi $(10) = 4. $\phi $(n) or to factorise n ); no-one knows of such a method, or if they do, they're keeping very quiet about it!

If you would like to calculate $\phi $(10) = 4. $\phi $(n) for yourself, the following fact is handy (no proof supplied!):

**Fact**

Let a, b be coprime positive whole numbers, then $\phi $(a b) = $\phi $(a) $\phi $(b).

Note: we must have that a and b are coprime because, for instance, $\phi $(4) = Size of {1,3} = 2. Whereas $\phi $(2) = Size of {1} = 1, and hence $\phi $(4) doesn't equal $\phi $(2) $\phi $(2).

Example: $\phi $(21) = $\phi $(3 * 7) = $\phi $(3) * $\phi $(7) = 2 * 6 = 12.

If you can't be bothered to calculate phi by hand, I've written a phi calculator which will do it for you.

**Warning!** Calculating $\phi $(n)
involves factorising n, which generally takes a long time for large
n. (which is why the RSA code is so effective!), so if you enter a
large number ( say >= 20 digits ), my programme may appear to
stall. Really, it's just thinking
very hard. :-(

Another related programme, which you may find useful later on is my factoriser:

The following program multiplies any two integers together (more useful than you might think!)

It's all very well messing about with numbers, but what about encrypting an actual message?!

One rather silly approach would be to assign each letter of
the alphabet to one of the elements of R(n). The drawback, as
with Caesar's method is that it effectively limits the number of
codes to only 26! (that's an exclamation point, and not the factorial
symbol.) So in order to increase the size of our
alphabet, we convert *blocks* of characters into integers.
The way we do this is first to assign an integer between 0 and
N-1 to each character (where there are a total of N characters in
our character set, e.g. N = 26 if we use the Roman alphabet as
our character set) then, having already chosen n, we define r to
the the unique positive integer such that
${N}^{r}\le n<{N}^{r+1}$.
Each block of r characters then corresponds to a base N
number which is between 0 and n-1 inclusive. When I get round to it, this will
be a link to a page about numbers in other bases. This
number is encoded using the map
$x\u27f6{x}^{e}$.
Now
${x}^{e}$
is between 0 and n-1 (mod n), but not necessarily less
than
${N}^{r}$,
so it converts to a block of r+1 characters (not a block of
r characters). To decode, we simply invert the entire
process. Note that we can only invert if x is coprime to n;
often, we will take n to be the product of two primes, say n = p
q, with p and q prime. Then the number of choices for x which are
coprime to n is $\phi $(n)
= $\phi $(p)$\phi $(q)
= (p-1)(q-1), which is close enough to n, for large p,q. If that's all
Greek to you, don't worry, because I have slaved away at my keyboard
and produced a Java applet which does the job for you:

I have spent the last two weeks learning the Java programming language just so that I could produce the following applet. I've written it so that you need to understand at least some of the maths in order to be able to use it.

Just punch in your number n, and a number e if you wish to encode and/or d if you wish to decode. Type your message in the appropriate window (I'll let you figure out which one is the appropriate window) and hit the encode or decode button. That's it.

As far as I know, there aren't any bugs in the program, but
sometimes it will produce error messages. This is because *you*
did something wrong ;-)

Error Message | Explanation |
---|---|

java.lang.NumberFormatException: Zero length BigInteger | You need to type in a number for n and for e or d |

java.lang.NumberFormatException: Choose n>95 | Do as it tells you! I have chosen N = 95. If n <= N, then the program won't be able to calculate r>0 such that ${N}^{r}\le n<{N}^{r+1}$. |

java.lang.NumberFormatException: 'x' isn't coprime to 'n' | This means that when one of the block of characters was converted to an integer x, x wasn't coprime to n. You can sometimes remedy this by simply adding a few extra characters at the beginning of your message. Otherwise, choose a decent n which has few factors! |

If you're not sure how to get the software running, here's a step-by-step list of what you have to do:

- Choose an integer n such that n >= 95. Preferably, n should have few factors.
- Figure out $\phi $(n). If you can use my phi calculator, then you've chosen a bad n, because anyone else can also use the phi calculator to get $\phi $(n), and you're code can be cracked! Instead, use the multiplicativity of $\phi $.
- Choose an encoding key, e which is coprime to $\phi $(n). You can check that any particular choice works by using the hcf calculator. The hcf of e and $\phi $(n) should be 1.
- Figure out the decoding key, d. You can do this using the hcf calculator. Type in $\phi $(n) where the programme asks you for a, and type in e where the program asks you for b. The output should be something like: ' hcf is 1 = s $\phi $(n) + t e' (where s and t will be actual numbers). Just take your d to be t. (so that d is the inverse of e mod $\phi $(n))
- If you want to encode a message, type n and e in the appropriate boxes and enter the message to be encoded in the window next to the 'encode' button. Hit the 'encode' button and the encoded message will appear in the other window.
- If you want to encode a message, type n and d in the appropriate boxes and enter the message to be decoded in the window next to the 'decode' button. Hit the 'decode' button and the decoded message will appear in the other window.

**Worked Example**

**N.B.**.: Often you will need the output
from one of the programmes above in order to calculate n, e and
d. Note that with most windows operating systems, you can copy
and paste from the text boxes. e.g. with Microsoft Windows, just
select the text to be copied with your mouse, then hit Ctrl-C to
copy and Ctrl-V to paste.

- First I mess around with the factoriser to find two large primes, e.g. p = 5465464567 and q = 6534535367. (In practise, you might like to try even larger primes, for extra security). We put n = pq.
- As p and q are coprime, $\phi $(n) = $\phi $(p)$\phi $(q). Because, p and q are prime $\phi $(p) = p-1 and $\phi $(q) = q-1. so $\phi $(n) = (p-1)(q-1) = 5465464566 * 6534535366 = 35714271498146841156 (use my multiplier to do the multiplication)
- Pick an integer e, it will probably work! e.g. try e = 35. I check it works (i.e. is coprime to $\phi $(n) ) using the hcf calculator. The calculator tells me that the hcf of 35 and 35714271498146841156 is indeed 1.
- The output from the hcf calculator is 'hcf is 1 = -16326524113438555957*35 + 16*35714271498146841156', so the decoding key, d, is -16326524113438555957
- To encode the string 'My name is Michel Cain', enter the data in the right places, then hit 'encode'. (note n = pq = 35714271510146841089). The encoded message is '(Im?*5AYe->X='|=tXL*wi%93@Ia!C' (without the apostrophes)
- I'll let you figure this step out yourself.

If you want to use my programme to receive messages from other people, you will typically tell them the numbers n and e, but keep the number d a secret. They can then encode messages and send them to you, but cannot decode anything!!. (Note that you can copy the output of CodeIt and paste it into your mail programme)

This section is for those who have not come across congruences or Euclid's algorithm. If this applies to you, read on, else feel free to skip it.

Congruences are a bit like equations, but different! We need congruences to describe the RSA code, so I guess I'll have to explain what they are ;-)

**Definition**

Let a, b, m be whole numbers. We say a is congruent b modulo m and write 'a $\equiv $b mod m' if m divides a-b.

For instance, 10 $\equiv $ 4 mod 2, as 2 divides 6 = 10-4. Also 24 $\equiv $ -1 mod 5, as 5 divides 25 = 24-(-1).

Sometimes, the idea of congruence arithmetic is introduced by looking at the arithmetic of clocks. Note that on a (twelve-hour) clock, if you add 3 to 10, you get 1 ( because 3:00 + 10:00 = 13:00 = 1pm ). More generally, whenever you add on a multiple of 12 hours, you get back the same position of the hour hand. What is really happening is that clock arithmetic is congruence arithmetic modulo 12; we make precise the statement that 3 + 10 '=' 1 by observing that 3 + 10 = 13 $\equiv $1 mod 12.

The reason we introduce congruences is that they behave in many ways like ordinary equations. First, they have some nice properties which enable you to combine congruences in simple ways e.g. if a, b, c, m are whole numbers then:

- a $\equiv $a mod m
- if a $\equiv $b mod m then b $\equiv $a mod m
- if a $\equiv $b mod m and b $\equiv $c mod m then a $\equiv $c mod m

Also, like ordinary equations, one can add and multiply congruences:

- if a $\equiv $b mod m and a' $\equiv $b' mod m then a + a' $\equiv $b + b' mod m
- if a $\equiv $b mod m and a' $\equiv $b' mod m then a * a' $\equiv $b * b' mod m

All these statements require proof, of course, but I'll leave them as exercises!

Next, we need something called Euclid's Algorithm in order to be able to find congruence inverses. Suppose we have whole numbers a and m such that a is coprime to m. We'd like to be able to find a whole number b such that a b $\equiv $1 mod m. If this were an ordinary equation then we'd just put b = 1/a, but of course, it isn't, and usually, 1/a won't even be a whole number. Instead we use a nifty result which shows the existence of whole numbers s and t, such that 1 = sa + tm. Then we just take b = s and we're done.

**Lemma (Euclid's Algorithm)**

Let a, b be whole numbers and let d = hcf(a,b) ( follow this link for a definition ) then there exist whole numbers s and t such that d = s a + t b.

**Proof**

It is a basic property of whole numbers that given a and b, there exist whole numbers q and r such that a = bq + r and, moreover, that 0<= r < |b|. One can check that hcf(a,b) = hcf(b,r). Then, by induction on r, we have that there exist s' and t' such that d = s' b + t' r. Consequently, d = s' b + t' (a - bq) = t' a + (s' - t'q)b. So put s = t' and t = s' - t'q, then d = sa + tb. QED.

Even if you don't get the proof, there's no need to worry as I've written a Java applet which will do the calculations for you. Click here for Gihan's hcf Calculator.

I am rather inexperienced with Java (at the date of writing, I've only been at it two weeks), so my software may seem a little rough round the edges. If you have any feedback on how to improve the programmes, please email me.

Java is meant to be platform and country independent, but I have sidestepped the latter feature by using the Unicode values of the characters in 'CodeIt'. This will cause problems if your operating system / web browser does not use the ASCII or ISO8859-1 (Latin-1) document encoding method.

All the software on this page uses the java.math package. (this package is new to Java 1.1, if you're browser doesn't support Java 1.1, get one that does! See the JavaSoft home page for more details) The package java.math defines a class BigInteger which supports arbitrary sized integers. This means that you can choose 'n' to be as large as you like in CodeIt.

RSA Data Security, Inc. | This company was set up by the guys who invented the RSA code. Unsurprisingly, they specialise in cryptography methods. |

This document was written in XHTML and MathML. To view it properly, you need an up-to-date browser, such as mozilla, and the required fonts.

On a modern Debian system, you should install the latex-xft-font debian package, then copy the Mathematica 4.1 fonts to /usr/local/share/fonts/math-fonts. You may also need to install the adobe symbol font as described in this document on installing MathML on linux. Restart mozilla and you're up!

If you're running mozilla on Windows, follow the instructions on the mozilla MathML webpage. You may need to save the file before running it if installation throws up errors.

This document is XHTML 1.1 compliant!