<

Tue Feb 06 2024

Understanding RSA

RSA is a beautifully simple algorithm for asymmetric encryption, which uses the properties of modular arithmetic to transmit small messages securely. This article presents a possible thought process from which the algorithm could be derived, based on some key mathematical facts.

Note: This article requires some knowledge of modular arithmetic.

A Small Overview

RSA is an asymmetric encryption algorithm, which means that its goal is to create a message which is encrypted using one key, but decrypted using a different one. In practice, it is a way to ensure that a message is only received by a specific person. To do this, the receiver of the messages creates a public encryption key, which any person can use to send them a message, and a decryption key, which they keep private and is the only way to read the messages sent.

The Key Insight

The starting point for the RSA algorithm is a simple fact derived from Euler's Theorem: If you have a congruence m\displaystyle{ m } (for message) in a modulo n\displaystyle{ n } , and they share no common factors, then there are infinitely many powers x\displaystyle{ x } such that:

mxm (mod n)\displaystyle{ m ^{ x } ≡ m \text{ (mod n)} }

For instance:

1251 (mod 35)\displaystyle{ 1 ^{ 25 } ≡ 1 \text{ (mod 35)} }
2252 (mod 35)\displaystyle{ 2 ^{ 25 } ≡ 2 \text{ (mod 35)} }
3253 (mod 35)\displaystyle{ 3 ^{ 25 } ≡ 3 \text{ (mod 35)} }
4254 (mod 35)\displaystyle{ 4 ^{ 25 } ≡ 4 \text{ (mod 35)} }

Basically, the entire exponentiation becomes a no-op. This may not seem very useful, but if we rewrite x\displaystyle{ x } as the product of two numbers, let's say, x=ed\displaystyle{ x = e \cdot d } , then, it must hold that:

medm (mod n)\displaystyle{ m ^{ e \cdot d } ≡ m \text{ (mod n)} }
(me)dm (mod n)\displaystyle{ \left( m ^{ e } \right) ^{ d } ≡ m \text{ (mod n)} }

Which, if you look at it, is exactly what we want. Anyone with the encryption key e\displaystyle{ e } can encode a message:

encrypted messageme (mod n)\displaystyle{ \text{encrypted message} ≡ m ^{ e } \text{ (mod n)} }

And, from the encrypted message, you can only recover the original one with the decryption key d\displaystyle{ d } .

(encrypted message)dm (mod n)\displaystyle{ \left( \text{encrypted message} \right) ^{ d } ≡ m \text{ (mod n)} }

This is the base of how the encryption scheme works. We create public n\displaystyle{ n } and e\displaystyle{ e } values, which anyone can use to encrypt a message, and we, and only we, can use our private key d\displaystyle{ d } to decrypt it. But now, we need to find a way of actually creating n\displaystyle{ n } , e\displaystyle{ e } and d\displaystyle{ d } , such that the original property holds, and more importantly, such that it is not easily possible to derive the decryption key d\displaystyle{ d } from the other variables, which would defeat the whole point.

Diving Deeper into Euler's Theorem

First of all, we must understand Euler's Theorem, the source of our key insight. It states that for a congruence m\displaystyle{ m } in a modulo n\displaystyle{ n } , with no common factors between m\displaystyle{ m } and n\displaystyle{ n } , it holds that:

mφ(n)1 (mod n)\displaystyle{ m ^{ φ \left( n \right) } ≡ 1 \text{ (mod n)} }

Where φ(n)\displaystyle{ φ \left( n \right) } is Euler's totient function, which requires finding the prime factors of n\displaystyle{ n } , and is generally hard to compute.

This equation, in turn, means that multiplying anything by mφ(n)\displaystyle{ m ^{ φ \left( n \right) } } has no effect (as it is congruent to 1), and we can do it freely. From this, we get that:

mmmφ(n)mmφ(n)mφ(n)mmφ(n)mφ(n)m1+qφ(n) (mod n)\displaystyle{ m ≡ m \cdot m ^{ φ \left( n \right) } ≡ m \cdot m ^{ φ \left( n \right) } \cdot m ^{ φ \left( n \right) } ≡ m \cdot m ^{ φ \left( n \right) } \cdot \ldots \cdot m ^{ φ \left( n \right) } ≡ m ^{ 1 + q φ \left( n \right) } \text{ (mod n)} }
mqφ(n)+1m (mod n)\displaystyle{ m ^{ q φ \left( n \right) + 1 } ≡ m \text{ (mod n)} }

Where q\displaystyle{ q } is a whole number.

Now, if we set x=ed=qφ(n)+1\displaystyle{ x = e \cdot d = q φ \left( n \right) + 1 } , we have recreated the original property:

mxmedm (mod n)\displaystyle{ m ^{ x } ≡ m ^{ e \cdot d } ≡ m \text{ (mod n)} }

We have also greatly constrained the possible values of e\displaystyle{ e } and d\displaystyle{ d } , with ed=qφ(n)+1\displaystyle{ e \cdot d = q φ \left( n \right) + 1 } . This equation can be rewritten in a modular form:

ed1 (mod φ(n))\displaystyle{ e \cdot d ≡ 1 \text{ (mod φ(n))} }
de1 (mod φ(n))\displaystyle{ d ≡ e ^{ - 1 } \text{ (mod φ(n))} }

This establishes a clear relationship between e\displaystyle{ e } and d\displaystyle{ d } , which can be further simplified by the fact that e\displaystyle{ e } is supposed to be public, which allows us to use a preset value (usually the prime 216+1\displaystyle{ 2 ^{ 16 } + 1 } ) without worrying too much about security. We then only need to make sure e\displaystyle{ e } is coprime with φ(n)\displaystyle{ φ \left( n \right) } for d\displaystyle{ d } to exist (made easier by the primality of e\displaystyle{ e } ). We have also gained an important requirement: To compute d\displaystyle{ d } , we basically only need to know φ(n)\displaystyle{ φ \left( n \right) } . This means φ(n)\displaystyle{ φ \left( n \right) } should be kept private as well. Then, finding d\displaystyle{ d } from e\displaystyle{ e } is just a multiplicative inverse, which can be done using the Extended Euclidean Algorithm.

Euler's Totient Function

To complete the algorithm, we need to actually compute φ(n)\displaystyle{ φ \left( n \right) } . For our purposes, it necessary to know that the totient function is computed with all of n\displaystyle{ n } 's unique prime factors p1,p2,,pk\displaystyle{ p _{ 1 } , p _{ 2 } , \ldots , p _{ k } } :

φ(n)=np11p1p21p2pk1pk\displaystyle{ φ \left( n \right) = n \cdot \frac{ p _{ 1 } - 1 }{ p _{ 1 } } \cdot \frac{ p _{ 2 } - 1 }{ p _{ 2 } } \cdot \ldots \cdot \frac{ p _{ k } - 1 }{ p _{ k } } }

For example, φ(12)=12(12)(23)=4\displaystyle{ φ \left( 12 \right) = 12 \cdot \left( \frac{ 1 }{ 2 } \right) \cdot \left( \frac{ 2 }{ 3 } \right) = 4 } , because the unique prime factors of 12\displaystyle{ 12 } are 2\displaystyle{ 2 } and 3\displaystyle{ 3 } . Computationally, this means that finding φ(n)\displaystyle{ φ \left( n \right) } requires factoring n\displaystyle{ n } , which is a famously hard problem to do efficiently with large numbers. On one hand, this means that people will not be able to easily compute φ(n)\displaystyle{ φ \left( n \right) } , and, by extension, d\displaystyle{ d } , which is exactly what we want. On the other hand, this also means we cannot either, which makes the entire algorithm unworkable.

The solution is to backwards: Instead of starting with an n\displaystyle{ n } and factoring it, we start with the prime factors and multiply them to compute n\displaystyle{ n } . The simplest non-trivial case for this is when n\displaystyle{ n } is a product of two primes n=pq\displaystyle{ n = p \cdot q } . Then,

φ(n)=φ(pq)=pqp1pq1q=(p1)(q1)\displaystyle{ φ \left( n \right) = φ \left( p \cdot q \right) = p \cdot q \cdot \frac{ p - 1 }{ p } \cdot \frac{ q - 1 }{ q } = \left( p - 1 \right) \left( q - 1 \right) }

Now, if we generate two primes, computing n\displaystyle{ n } and φ(n)\displaystyle{ φ \left( n \right) } is trivial, but, given n\displaystyle{ n } , finding φ(n)\displaystyle{ φ \left( n \right) } requires finding the factors p\displaystyle{ p } and q\displaystyle{ q } , which for large enough numbers, becomes computationally unfeasible. This is the last step to our puzzle, and we are ready to describe the algorithm in full.

Putting It All Together

The first step in our algorithm is to generate two primes, p\displaystyle{ p } and q\displaystyle{ q } , from which we can compute our n=pq\displaystyle{ n = p \cdot q } and φ(n)=(p1)(q1)\displaystyle{ φ \left( n \right) = \left( p - 1 \right) \left( q - 1 \right) } . We share n\displaystyle{ n } with everyone, as part of our public key, while keeping the other values private.

We then choose a value for our e\displaystyle{ e } , usually e=216+1\displaystyle{ e = 2 ^{ 16 } + 1 } , and share it as the final part of our public encryption key. Then, using our private φ(n)\displaystyle{ φ \left( n \right) } , we compute the private decryption key de1 (mod φ(n))\displaystyle{ d ≡ e ^{ - 1 } \text{ (mod φ(n))} } . We have now finished the key generation, and it is time to send some messages.

Any person that knows both n\displaystyle{ n } and e\displaystyle{ e } can encrypt a message m\displaystyle{ m } with a simple exponential:

encrypted messageme (mod n)\displaystyle{ \text{encrypted message} ≡ m ^{ e } \text{ (mod n)} }

This message cannot be decrypted by anyone, even the original sender, without the private decryption key d\displaystyle{ d } . Since we know it, we can decrypt it just as easily as it was encrypted:

m(encrypted message)d (mod n)\displaystyle{ m ≡ \left( \text{encrypted message} \right) ^{ d } \text{ (mod n)} }

And thus, we have gotten back the original message, without the possibility of snooping by third parties.

Conclusion

In this article we have gone through the mathematical principles that allow the RSA algorithm to work, alongside a possible process for going from these insights to an actual algorithm. That said, there is still some more to it. First of all, generating large primes is not trivial, and requires the use of probabilistic primality tests, like Miller-Rabin. Similarly, the Extended Euclidean Algorithm is rather complex, at least conceptually. There are also many possible optimizations, like replacing the totient function with the reduced totient function, for which Euler's Theorem also holds. Finally, it is very important to know that you must be very mindful about security with RSA, as it is extremely easy to shoot yourself in the foot, making the entire algorithm unsecure. If you are not an expert, do not ever use a home-baked implementation of RSA for anything that actually needs to be secure. That said, understanding and implementing RSA is a fun and relatively easy project, and trying to improve its speed an security is a great learning experience in math, programming, and cryptography.


contact