%PDF- %PDF-
| Direktori : /data/down/eBOOKS/Handbook of Applied Cryptography/ |
| Current File : //data/down/eBOOKS/Handbook of Applied Cryptography/montexpo.c |
/*
Author: Pate Williams (c) 1997
Montgomery exponentiation. See "Handbook of Applied
Cryptography" by Alfred J. Menezes et al Section
14.6.1 pages 614 - 620.
*/
#include <stdio.h>
#include <stdlib.h>
#include "lip.h"
#define DEBUG
void radix_representation(long b, long n, long *a, verylong za)
{
long i = 0;
verylong zb = 0, zq = 0, zr = 0, zx = 0;
zintoz(b, &zb);
zcopy(za, &zx);
do {
zdiv(zx, zb, &zq, &zr);
a[i++] = ztoint(zr);
zcopy(zq, &zx);
} while (zscompare(zq, 0l) != 0);
while (i < n) a[i++] = 0;
zfree(&zb);
zfree(&zq);
zfree(&zr);
zfree(&zx);
}
void Montgomery_multiplication(long b, long n,
verylong zm, verylong zx,
verylong zy, verylong *zA)
{
long i, n1 = n + 1, u, mp, *a, *m, *x, *y;
verylong za = 0, zb = 0, zc = 0, zd = 0, zs = 0;
a = calloc(n1, sizeof(long));
m = calloc(n1, sizeof(long));
x = calloc(n1, sizeof(long));
y = calloc(n1, sizeof(long));
if (a == 0 || m == 0 || x == 0 || y == 0) {
printf("*error*\ncan't get memory from Montgomery");
printf(" multiplication");
exit(1);
}
zintoz(b, &zb);
zinvmod(zm, zb, &za);
znegate(&za);
mp = zsmod(za, b);
radix_representation(b, n1, m, zm);
radix_representation(b, n1, x, zx);
radix_representation(b, n1, y, zy);
zzero(zA);
for (i = 0; i < n; i++) {
radix_representation(b, n1, a, *zA);
u = ((a[0] + x[i] * y[0]) * mp) % b;
zsmul(zy, x[i], &za);
zsmul(zm, u, &zc);
zadd(*zA, za, &zs);
zadd(zs, zc, &zd);
zsdiv(zd, b, zA);
}
if (zcompare(*zA, zm) >= 0) {
zsub(*zA, zm, &za);
zcopy(za, zA);
}
free(a);
free(m);
free(x);
free(y);
zfree(&za);
zfree(&zb);
zfree(&zc);
zfree(&zd);
zfree(&zs);
}
void Montgomery_exponentiation(char *e, long b, long l, long t,
verylong zR, verylong zm,
verylong zx, verylong *zA)
{
long i;
verylong za = 0, zb = 0, zxp = 0;
zmulmod(zR, zR, zm, &zb);
Montgomery_multiplication(b, l, zm, zx, zb, &zxp);
zmod(zR, zm, zA);
for (i = t; i >= 0; i--) {
Montgomery_multiplication(b, l, zm, *zA, *zA, &za);
zcopy(za, zA);
if (e[i] == 1) {
Montgomery_multiplication(b, l, zm , *zA, zxp, &za);
zcopy(za, zA);
}
#ifdef DEBUG
zwriteln(*zA);
#endif
}
zone(&zxp);
Montgomery_multiplication(b, l, zm, *zA, zxp, &za);
zcopy(za, zA);
zfree(&za);
zfree(&zb);
zfree(&zxp);
}
int main(void)
{
char e[4] = {1, 1, 0, 1};
long b = 10, l = 5, t = 3;
verylong zA = 0, zR = 0, za = 0, zm = 0, zx = 0;
zintoz(100000l, &zR);
zintoz(72639l, &zm);
zintoz(5792l, &zx);
Montgomery_exponentiation(e, b, l, t, zR, zm, zx, &zA);
zsexpmod(zx, 11, zm, &za);
zwriteln(za);
zwriteln(zA);
zfree(&zA);
zfree(&zR);
zfree(&za);
zfree(&zm);
zfree(&zx);
return 0;
}