 |
Modular exponentiation
We shall now learn how to compute ab (mod m)
where a, b and m are given numbers. The main
problem is as for modular multiplication: we cannot compute
ab directly as it might be too large.
We have already learned from modular multiplication that we
should break the problem into steps, and perform modul reduction
after each step. This prevents the numbers from growing too much.
The question is: How to break up the computation of ab into steps.
A simple way to compute ab step by
step is to compute a, a2,
a3 and so on, performing modular reduction at
each step. This works, but if b is too large (say, 100
digits) this will
take l...o...n...g!!!
We shall now learn another way to break the problem into steps.
For this we start by expressing the number b in binary.
Let the bits of b be
bk-1, bk-2, ..., b1, b0.
| Example:
If b=53 we shall write (using k=8 bits, say)
b = (00110101)2.
Thus here
b0 = 1
b1 = 0
b2 = 1
b3 = 0
b4 = 1
b5 = 1
b6 = 0
b7 = 0
|
Then
b = b0 20 + ..., + bk-1 2k-1,
and so
ab = (c0)b0
(c1)b0
...
(ck-1)bk-1.
where
ci = a2i.
Observe that
c0 = a
and
ci = ci-1 2
We shall perform all the computation modulo m.
| Example:
Taking a=3 we comoute ci's as follows (with
k=8 and m=6254):
c0 = 3
c1 = 9
c2 = 81
c3 = 307
c4 = 439
c5 = 5101
c6 = 3561
c7 = 3863
c8 = 725
|
Now observe that the product in (**) is basically the product of
those ci's for which bi's are 1.
| Example:
In our example, b0 = b2 = b4 = b5 = 1.
So we need to form the product
c0 c2 c4 c5 (mod m).
c0 c2 = 3 * 81 = 243
(c0 c2) c4 = 243 * 439 = 359
(c0 c2 c4) c5 = 359 * 5101 = 5091
Thus we finally see that
353 = 5091 (mod 6254).
|
Let us package this as a C function that we can use later:
unsigned int modExpo(unsigned int a, unsigned int b, unsigned int m) {
unsigned int ans, ci;
ci = a % m;
ans = 1;
for(i=0;i<k;i++) {
ci = modMult(ci, ci, m);
if((b & (1<<i)) != 0) {
ans = modMult(ans, ci, m);
}
}
return ans;
}
Testing
Here is a complete C program ready to be compiled and run:
#include <stdio.h>
int k = 32;
unsigned int modMult(unsigned int a, unsigned int b, unsigned int m) {
unsigned int ans, ci;
di = a % m;
ans = 0;
for(i=0;i<k;i++) {
di = (ci << 1) % m;
if((b & (1<<i)) != 0) {
ans = ans + di;
}
}
return ans;
}
unsigned int modExpo(unsigned int a, unsigned int b, unsigned int m) {
unsigned int ans, ci;
ci = a % m;
ans = 1;
for(i=0;i<k;i++) {
ci = modMult(ci, ci, m);
if((b & (1<<i)) != 0) {
ans = modMult(ans, ci, m);
}
}
return ans;
}
main() {
unsigned int y;
y = modExpo(3,53,6254);
printf("3 to the power 53 = %u mod 6254.\n",y);
}
Where do we stand?
In this and the last page we have learned how to perform
modular multiplication and modular exponentiation. These are
important building blocks in many cryptosystems, including RSA.
We shall not extend these algorithms any further. In the next
page we shall learn how to compute gcd of two numbers using the
Extended Euclidean Algorithm. This algorithm has nothing to do
with modular multiplication or exponentiation.
|