/* Author: Pate Williams (c) 1997 The following program implements and tests two algorithms for solving the discrete logarithm problem. The algorithms are baby-step giant-step and Pollard's rho algorithms. The implementations are from "Handbook of Applied Cryptography" by Alfred J. Menezes et al pages 103 - 107. */ #include #include #include "lip.h" struct Element { long index; verylong alpha_index; }; long Find(long n, verylong value, struct Element *array) { long c, hi = n - 1, lo = 0, mid; for (;;) { mid = (hi + lo) / 2; c = zcompare(value, array[mid].alpha_index); if (c == 0) return mid; if (c < 0) hi = mid - 1; else lo = mid + 1; if (lo > hi) return - 1; } } int BabyStepGiantStep(verylong zalpha, verylong zbeta, verylong zn, verylong zp, verylong *zx) /* given a generator alpha of a cyclic group G of order n and an element beta compute the discrete logarithm x returns 0 if not enough memory for the problem 1 otherwise */ { long i, j, m; static verylong za = 0, zd = 0, zg = 0, zm = 0; struct Element *element, temp; zsqrt(zn, &za, &zd); zsadd(za, 1l, &zm); m = ztoint(zm); element = (struct Element *) malloc(m * sizeof(struct Element)); if (element == 0) return 0; zone(&zd); /* construct table */ for (i = 0; i < m; i++) { element[i].index = i; element[i].alpha_index = 0; zcopy(zd, &element[i].alpha_index); zmul(zd, zalpha, &za); zmod(za, zp, &zd); } /* sort on second values */ for (i = 0; i < m - 1; i++) { for (j = i + 1; j < m; j++) { if (zcompare(element[i].alpha_index, element[j].alpha_index) > 0) { temp = element[i]; element[i] = element[j]; element[j] = temp; } } } zinvmod(zalpha, zp, &za); zexp(za, zm, &zg); zmod(zg, zp, &zd); zcopy(zbeta, &zg); for (i = 0; i < m; i++) { printf("%d ", element[i].index); zwriteln(element[i].alpha_index); } for (i = 0; i < m; i++) { j = Find(m, zg, element); if (j != - 1) { zsmul(zm, i, &za); zsadd(za, j, zx); for (j = 0; j < m; j++) zfree(&element[j].alpha_index); free(element); return 1; } zmul(zg, zd, &za); zmod(za, zp, &zg); } return 0; } void zai(verylong za0, verylong zn, verylong zx0, verylong *za1) { long x = zsmod(zx0, 3l); static verylong za = 0; if (x == 1) zcopy(za0, za1); else if (x == 0) { zsmul(za0, 2l, &za); zmod(za, zn, za1); } else { zsadd(za0, 1l, &za); zmod(za, zn, za1); } } void zbi(verylong zb0, verylong zn, verylong zx0, verylong *zb1) { long x = zsmod(zx0, 3l); static verylong zb = 0; if (x == 1) { zsadd(zb0, 1l, &zb); zmod(zb, zn, zb1); } else if (x == 0) { zsmul(zb0, 2l, &zb); zmod(zb, zn, zb1); } else zcopy(zb0, zb1); } void zfi(verylong zalpha, verylong zbeta, verylong zp, verylong zx0, verylong *zx1) { long x = zsmod(zx0, 3l); if (x == 1) zmulmod(zbeta, zx0, zp, zx1); else if (x == 0) zmulmod(zx0, zx0, zp, zx1); else zmulmod(zalpha, zx0, zp, zx1); } int PollardRho(verylong zalpha, verylong zbeta, verylong zn, verylong zp, verylong *zx) { long i = 2, j; static verylong za0 = 0, za1 = 0, za2 = 0, za3 = 0; static verylong zb0 = 0, zb1 = 0, zb2 = 0, zb3 = 0; static verylong zx0 = 0, zx1 = 0, zx2 = 0, zx3 = 0; static verylong zr = 0, zri = 0; zone(&zx0); zzero(&za0); zzero(&zb0); zfi(zalpha, zbeta, zp, zx0, &zx1); zai(za0, zn, zx0, &za1); zbi(zb0, zn, zx0, &zb1); zfi(zalpha, zbeta, zp, zx1, &zx2); zai(za1, zn, zx1, &za2); zbi(zb1, zn, zx1, &zb2); zcopy(za1, &za0); zcopy(zb1, &zb0); zcopy(zx1, &zx0); for (;;) { zfi(zalpha, zbeta, zp, zx0, &zx1); zai(za0, zn, zx0, &za1); zbi(zb0, zn, zx0, &zb1); zcopy(za1, &za2); zcopy(zb1, &zb2); zcopy(zx1, &zx2); i++; for (j = 0; j < i; j++) { zfi(zalpha, zbeta, zp, zx2, &zx3); zai(za2, zn, zx2, &za3); zbi(zb2, zn, zx2, &zb3); zcopy(za3, &za2); zcopy(zb3, &zb2); zcopy(zx3, &zx2); } if (zcompare(zx1, zx3) == 0) { zsubmod(zb1, zb3, zn, &zr); if (zscompare(zr, 0) == 0) return 0; zinvmod(zr, zn, &zri); zsub(za3, za1, &za0); zmulmod(za0, zri, zn, zx); return 1; } zcopy(za1, &za0); zcopy(zb1, &zb0); zcopy(zx1, &zx0); } } int main(void) { verylong zalpha = 0, zbeta = 0, zn = 0, zp = 0, zx = 0; zintoz(3l, &zalpha); zintoz(57l, &zbeta); zintoz(112l, &zn); zintoz(113l, &zp); BabyStepGiantStep(zalpha, zbeta, zn, zp, &zx); printf("the discrete logarithm of 57 base 3 = "); zwriteln(zx); zintoz(2l, &zalpha); zintoz(228l, &zbeta); zintoz(191l, &zn); zintoz(383l, &zp); PollardRho(zalpha, zbeta, zn, zp, &zx); printf("the discrete logarithm of 228 base 2 = "); zwriteln(zx); zfree(&zalpha); zfree(&zbeta); zfree(&zn); zfree(&zp); zfree(&zx); return 0; }