Cryptographic Algorithms

Embed Size (px)

DESCRIPTION

engineering

Citation preview

Table of Contents

Chapter 02

Mathematical Background

2.107

Algorithm Extended Euclidean Algorithm exteuc.c (1,378)

2.142

Algorithm Computing multiplicative inverses in Zn inverse.c

(1,094)

2.143

Algorithm Repeated square-and-multiply algorithm for

exponentiation in Zn repeat.c (1,268)

2.149

Algorithm Jacobi symbol (and Legendre symbol) computation

jacobi.c (987)

2.221

Algorithm Extended Euclidean algorithm in Zp[x] polyee.c freelip

(8,642)

2.107

Algorithm Extended Euclidean Algorithm exteuc.c (1,378)

/*

Author: Pate Williams (c) 1997

2.107 Algorithm Extended Euclidean algorithm

See "Handbook of Applied Cryptography" by

Alfred J. Menezes et al page 67.

*/

#include

#define DEBUG

void extended_euclid(long a, long b, long *x,

long *y, long *d)

/* calculates a * *x + b * *y = gcd(a, b) = *d */

{

long q, r, x1, x2, y1, y2;

if (b == 0) {

*d = a, *x = 1, *y = 0;

return;

}

x2 = 1, x1 = 0, y2 = 0, y1 = 1;

#ifdef DEBUG

printf("------------------------------");

printf("-------------------\n");

printf("q r x y a b ");

printf("x2 x1 y2 y1\n");

printf("------------------------------");

printf("-------------------\n");

#endif

while (b > 0) {

q = a / b, r = a - q * b;

*x = x2 - q * x1, *y = y2 - q * y1;

a = b, b = r;

x2 = x1, x1 = *x, y2 = y1, y1 = *y;

#ifdef DEBUG

printf("%4ld %4ld %4ld %4ld ", q, r, *x, *y);

printf("%4ld %4ld %4ld %4ld ", a, b, x2, x1);

printf("%4ld %4ld\n", y2, y1);

#endif

}

*d = a, *x = x2, *y = y2;

#ifdef DEBUG

printf("------------------------------");

printf("-------------------\n");

#endif

}

int main(void)

{

long a = 4864, b = 3458, d, x, y;

extended_euclid(a, b, &x, &y, &d);

printf("x = %ld y = %ld d = %ld\n", x, y, d);

return 0;

}

2.142

Algorithm Computing multiplicative inverses in Zn inverse.c (1,094)

/*

Author: Pate Williams (c) 1997

2.142 Algorithm Computing multiplicative

inverses in Zn

See "Handbook of Applied Cryptography" by

Alfred J. Menezes et al page 71.

*/

#include

void extended_euclid(long a, long b, long *x,

long *y, long *d)

/* calculates a * *x + b * *y = gcd(a, b) = *d */

{

long q, r, x1, x2, y1, y2;

if (b == 0) {

*d = a, *x = 1, *y = 0;

return;

}

x2 = 1, x1 = 0, y2 = 0, y1 = 1;

while (b > 0) {

q = a / b, r = a - q * b;

*x = x2 - q * x1, *y = y2 - q * y1;

a = b, b = r;

x2 = x1, x1 = *x, y2 = y1, y1 = *y;

}

*d = a, *x = x2, *y = y2;

}

long inverse(long a, long n)

/* computes the inverse of a modulo n */

{

long d, x, y;

extended_euclid(a, n, &x, &y, &d);

if (d == 1) return x;

return 0;

}

int main(void)

{

long a = 5, n = 7;

printf("the inverse of %ld modulo %2ld is %ld\n",

a, n, inverse(a, n));

a = 2, n = 12;

printf("the inverse of %ld modulo %2ld is %ld\n",

a, n, inverse(a, n));

return 0;

}

2.143

Algorithm Repeated square-and-multiply algorithm for

exponentiation in Zn repeat.c (1,268)

/*

Author: Pate Williams (c) 1997

2.143 Algorithm Repeated sqaure-and-mutiply

algorithm for exponentiation in Zn

See "Handbook of Applied Cryptography" by

Alfred J. Menezes et al page 71.

*/

#include

#define BITS_PER_LONG 32l

#define DEBUG

long long_to_binary(long K, long *k)

{

int found = 0;

long a = K, i, l = 0, length;

while (!found && l < BITS_PER_LONG) {

found = ((a & 0x80000000l) >> 31) == 1;

if (!found) a = 1;

return length;

}

long powmod(long a, long K, long n)

{

long A = a, b = 1, i, k[32];

long t = long_to_binary(K, k);

if (K == 0) return b;

if (k[0] == 1) b = a;

#ifdef DEBUG

printf("-------------\n");

printf("i k A B \n");

printf("-------------\n");

printf("%ld %ld %4ld %4ld\n", i = 0, k[i], A, b);

#endif

for (i = 1; i < t; i++) {

A = (A * A) % n;

if (k[i]) b = (A * b) % n;

#ifdef DEBUG

printf("%ld %ld %4ld %4ld\n", i, k[i], A, b);

#endif

}

#ifdef DEBUG

printf("-------------\n");

#endif

return b;

}

int main(void)

{

long a = 5, K = 596, n = 1234;

powmod(a, K, n);

return 0;

}

2.149

Algorithm Jacobi symbol (and Legendre symbol) computation

jacobi.c (987)

/*

Author: Pate Williams (c) 1997

2.149 Algorithm Jacobi symbol (and Legendre

symbol) computation

See "Hanbook of Applied Cryptography" by

Alfred J. Menezes et al page 73.

*/

#include

int JACOBI(long a, long n)

{

int s;

long a1, b = a, e = 0, m, n1;

if (a == 0) return 0;

if (a == 1) return 1;

while ((b & 1) == 0)

b >>= 1, e++;

a1 = b;

m = n % 8;

if (!(e & 1)) s = 1;

else if (m == 1 || m == 7) s = + 1;

else if (m == 3 || m == 5) s = - 1;

if (n % 4 == 3 && a1 % 4 == 3) s = - s;

if (a1 != 1) n1 = n % a1; else n1 = 1;

return s * JACOBI(n1, a1);

}

int main(void)

{

int j, k;

long a = 158, n = 235;

printf("a = %ld n = %ld (a / n) = %ld\n",

a, n, JACOBI(a, n));

for (a = 1; a < 21; a++) {

j = JACOBI(a, 3);

k = JACOBI(a, 7);

if (j != 0 && k != 0)

printf("%2ld %2ld %2d %2d %2d\n", a, a * a % 21,

j, k, JACOBI(a, 21));

}

return 0;

}

2.221

Algorithm Extended Euclidean algorithm in Zp[x] polyee.c freelip

(8,642)

/*

Author: Pate Williams (c) 1997

Polynomial extended Euclidean algorithm. See

"Handbook of Applied Cryptography" by Alfred

J. Menezes et al 2.6.2 Section 2.2.1 Algorithm

page 82.

*/

#include

#include "lip.h"

#define DEBUG

#define POLY_SIZE 8192l

void zpoly_mul(long m, long n, verylong *za, verylong *zb,

verylong *zc, long *p)

{

long i, j, k;

verylong zd = 0, zai = 0, zbk = 0, zsum = 0, zterm = 0;

*p = m + n;

for (k = 0; k n) zzero(&zbk);

else zcopy(zb[j], &zbk);

zmul(zai, zbk, &zterm);

zcopy(zsum, &zd);

zadd(zterm, zd, &zsum);

}

zcopy(zsum, &zc[k]);

}

zfree(&zd);

zfree(&zai);

zfree(&zbk);

zfree(&zsum);

zfree(&zterm);

}

void zpoly_div(long m, long n, verylong *zu, verylong *zv,

verylong *zq, verylong *zr, long *p, long *s)

{

long j, jk, k, nk;

verylong za = 0, zb = 0, zvn = 0;

zcopy(zv[n], &zvn);

for (j = 0; j = 0; k--) {

nk = n + k;

zsexp(zvn, k, &za);

zmul(zr[nk], za, &zq[k]);

for (j = nk - 1; j >= 0; j--) {

jk = j - k;

if (jk >= 0) {

zmul(zvn, zr[j], &za);

zmul(zr[nk], zv[jk], &zb);

zsub(za, zb, &zr[j]);

}

else {

zcopy(zr[j], &za);

zmul(zvn, za, &zr[j]);

}

}

}

while (*p > 0 && zscompare(zq[*p], 0l) == 0) *p = *p - 1;

while (*s > 0 && zscompare(zr[*s], 0l) == 0) *s = *s - 1;

}

zfree(&za);

zfree(&zb);

zfree(&zvn);

}

void zpoly_pow(long degreeA, long degreem, verylong zn,

verylong *zA, verylong *zm, verylong *zs,

long *ds)

{

long dp, dq, dx = degreeA, i;

verylong za = 0, zb = 0, zp[POLY_SIZE], zq[POLY_SIZE],

zx[POLY_SIZE], zy[POLY_SIZE];

for (i = 0; i < POLY_SIZE; i++)

zp[i] = zq[i] = zx[i] = zy[i] = 0;

*ds = 0;

zcopy(zn, &za);

zone(&zs[0]);

for (i = 0; i 0) {

if (zodd(za)) {

/* s = (s * x) % m; */

zpoly_mul(*ds, dx, zs, zx, zp, &dp);

zpoly_div(dp, degreem, zp, zm, zq, zs, &dq, ds);

}

zcopy(za, &zb);

zrshift(zb, 1l, &za);

if (zscompare(za, 0l) > 0) {

/* x = (x * x) % m; */

for (i = 0; i = db) {

for (i = 0; i next = currentPtr;

}

return 1;

}

void Delete(NodePtr *list)

{

NodePtr currentPtr = *list, tempPtr;

while (currentPtr != 0) {

zfree(&currentPtr->value);

tempPtr = currentPtr;

currentPtr = currentPtr->next;

free(tempPtr);

}

*list = 0;

}

void zpow(long base, long exponent, verylong *zs)

{

static verylong za = 0, zt = 0;

zone(zs);

zzero(&zt);

zsadd(zt, base, &zt);

while (exponent > 0) {

zcopy(*zs, &za);

if ((exponent & 1) == 1) zmul(za, zt, zs);

exponent >>= 1;

zcopy(zt, &za);

zmul(za, za, &zt);

}

}

int MillerRabin(int C, verylong zn)

{

int i, j, k = 0;

static verylong za = 0, zb = 0, zar = 0, zn1 = 0, zr = 0;

zsadd(zn, - 1l, &zn1);

zcopy(zn1, &zr);

if (zscompare(zn, 4l) < 1) return 1;

if (zsmod(zn, 2l) == 0) return 0;

while (zsmod(zr, 2l) == 0) {

k++;

zcopy(zr, &za);

zsdiv(za, 2l, &zr);

if (zsmod(zr, 2l) == 1l) break;

}

for (j = 0; j < C; j++) {

zrandomb(zn1, &za);

if (zscompare(za, 2l) < 0) {

zzero(&zb);

zsadd(zb, 2, &za);

}

zexpmod(za, zr, zn, &zar);

if (zscompare(zar, 1l) != 0 && zcompare(zar, zn1) != 0) {

i = 0;

do {

zcopy(zar, &za);

zmul(za, za, &zar);

zcopy(zar, &za);

zmod(za, zn, &zar);

if (zcompare(zar, zn1) == 0) break;

i++;

} while (i < k);

if (i == k) return 0;

}

}

return 1;

}

int FirstStage(long k, verylong *zN, long x0, long *p,

verylong *zx, NodePtr *list)

{

long c = 0, i = - 1, j = i, l, q, q1;

static verylong zg = 0, zq1 = 0, zt = 0, zx1 = 0, zy = 0;

zzero(&zg);

zsadd(zg, x0, zx);

zcopy(*zx, &zy);

L2:

i++;

if (i >= k) {

zsadd(*zx, - 1l, &zx1);

zgcd(zx1, *zN, &zg);

if (zscompare(zg, 1l) == 0) return 0;

else {

i = j;

zcopy(zy, zx);

goto L5;

}

}

else {

q = p[i];

q1 = q;

l = B / q;

}

L3:

while (q1 value);

if (node->expon != 1)

printf(" ^ %ld\n", node->expon);

else

printf("\n");

}

Delete(&list);

free(p);

}

zfree(&zn);

zfree(&zx);

time = (clock() - time0) / (double) CLK_TCK;

printf("total time required: %lf seconds\n", time);

return 0;

}

3.21

Algorithm Quadratic sieve algorithm for factoring integers mpqs.c

freelip (13,128)

/*

Author: Pate Williams (c) 1997

Quadratic sieve factoring algorithm. See

"Handbook of Applied Cryptography" by

Alfred J. Menezes et al 3.21 Algorithm page 96.

Also see "A Course in Computational

Algebraic Number Theory" by Henri Cohen

Section 10.4.2 pages 492 - 493.

The command line is as follows:

mpqs number_primes long_integer

where long_integer is to be factored or

mpqs number_primes base exponent addend

where the number base ^ exponent + addend

is to be factored.

*/

#include

#include

#include

#include

#include "lip.h"

#define LARGE_PRIME_LIMIT 10000l

#define NUMBER_PRIMES 1229l

#define TRIAL_DIVIDE_LIMIT 100000l

typedef struct Node * NodePtr;

struct Node {

long expon;

verylong value;

NodePtr next;

};

int Insert(int e, verylong v, NodePtr *list)

{

NodePtr currentPtr, newPtr, previousPtr;

newPtr = malloc(sizeof(struct Node));

if (newPtr == 0) return 0;

newPtr->expon = e;

newPtr->value = 0;

zcopy(v, &newPtr->value);

previousPtr = 0;

for (currentPtr = *list; currentPtr != 0 &&

zcompare(v, currentPtr->value) > 0; currentPtr = currentPtr->next)

previousPtr = currentPtr;

if (currentPtr != 0 && zcompare(v, currentPtr->value) == 0) {

currentPtr->expon++;

zfree(&newPtr->value);

free(newPtr);

}

else if (previousPtr == 0) {

newPtr->next = *list;

*list = newPtr;

}

else {

previousPtr->next = newPtr;

newPtr->next = currentPtr;

}

return 1;

}

void Delete(NodePtr *list)

{

NodePtr currentPtr = *list, tempPtr;

while (currentPtr != 0) {

zfree(&currentPtr->value);

tempPtr = currentPtr;

currentPtr = currentPtr->next;

free(tempPtr);

}

*list = 0;

}

long Find(long value, long *array)

{

long hi = NUMBER_PRIMES - 1, lo = 0, mid;

for (;;) {

mid = (hi + lo) / 2;

if (value == array[mid]) return mid;

if (value < array[mid]) hi = mid - 1;

else lo = mid + 1;

if (lo > hi) return - 1;

}

}

void zpow(long base, long exponent, verylong *zs)

{

static verylong za = 0, zt = 0;

zone(zs);

zzero(&zt);

zsadd(zt, base, &zt);

while (exponent > 0) {

zcopy(*zs, &za);

if ((exponent & 1) == 1) zmul(za, zt, zs);

exponent >>= 1;

zcopy(zt, &za);

zmul(za, za, &zt);

}

}

void zQx(long x, verylong zA, verylong zB, verylong zN, verylong *zQ)

/* Q(x) = ((A * x + B) ^ 2 - N) / A */

{

static verylong zu = 0, zv = 0;

zintoz(x, &zv);

zmul(zv, zA, &zu);

zadd(zu, zB, &zv);

zmul(zv, zv, &zu);

zsub(zu, zN, &zv);

zdiv(zv, zA, zQ, &zu);

}

int TrialDivision(char *e, long t, long *p, long *q, verylong *zq)

/* returns 1 if number can be factored using the prime base

and possibly one large prime */

{

long count, i, r;

static verylong zr = 0;

for (i = 0; i < t; i++) e[i] = 0;

if (zscompare(*zq, 0l) < 0) {

e[0] = 1;

znegate(zq);

}

for (i = 1; i < t; i++) {

r = p[i];

if (zsmod(*zq, r) == 0l) {

count = 0;

do {

count++;

zsdiv(*zq, r, &zr);

zcopy(zr, zq);

} while (zsmod(*zq, r) == 0);

e[i] = (char) count;

if (zscompare(*zq, 1l) == 0) return 1;

if (zprobprime(*zq, 5)) {

if (zscompare(*zq, LARGE_PRIME_LIMIT) value) == 0;

if (!found) l = l->next;

}

if (found) l->expon++;

else

Insert(count, zp, list);

flag1 = zscompare(*zn, 1l) == 0;

flag2 = zprobprime(*zn, 5);

}

} while (p = 0)

zmod(*zn, zA, &zr);

else

zcopy(*zn, &zr);

zsqrtmod(zr, zA, &zB);

zcopy(zB, &zb);

zmul(zb, zb, &za);

zsub(za, *zn, &zb);

zcopy(zB, &zD);

znegate(&zD);

zdiv(zB, zA, &za, &zb);

zcopy(za, &zb);

znegate(&zb);

zsadd(zb, b_min, &zt);

x_min = ztoint(zt);

zsadd(za, b_max, &zt);

x_max = ztoint(zt);

/* calculate the roots of the polynomial modulo the prime base */

for (l = 1; l < t; l++) {

r = p[l];

zintoz(r, &zt);

if (zcompare(*zn, zt) >= 0)

zmod(*zn, zt, &zr);

else

zcopy(*zn, &zr);

zsqrtmod(zr, zt, &za);

s = ztoint(za);

zsadd(zD, s, &zt);

zdiv(zt, zA, &za, &zb);

x1[l] = zsmod(za, r);

zsadd(zD, - s, &zt);

zdiv(zD, zA, &za, &zb);

x2[l] = zsmod(za, r);

}

for (x = x_min; x next) {

printf("\t");

zwrite(node->value);

if (node->expon != 1)

printf(" ^ %ld\n", node->expon);

else

printf("\n");

}

if (!flag) printf("last factor is composite\n");

}

}

Delete(&list);

}

zfree(&zn);

time = (clock() - time0) / (double) CLK_TCK;

printf("total time required: %f seconds\n", time);

return 0;

}

3.34

Algorithm Finding square roots modulo a prime p sqrtmod.c (3,090)

/*

Author: Pate Williams (c) 1998

3.34 Algorithm Finding square roots modulo a prime.

See "Handbook of Applied Cryptography" by Alfred J.

Menezes et al page 100.

*/

#include

#include

int JACOBI(long a, long n)

{

int s;

long a1, b = a, e = 0, m, n1;

if (a == 0) return 0;

if (a == 1) return 1;

while ((b & 1) == 0)

b >>= 1, e++;

a1 = b;

m = n % 8;

if (!(e & 1)) s = 1;

else if (m == 1 || m == 7) s = + 1;

else if (m == 3 || m == 5) s = - 1;

if (n % 4 == 3 && a1 % 4 == 3) s = - s;

if (a1 != 1) n1 = n % a1; else n1 = 1;

return s * JACOBI(n1, a1);

}

void extended_euclid(long a, long b, long *x,

long *y, long *d)

/* calculates a * *x + b * *y = gcd(a, b) = *d */

{

long q, r, x1, x2, y1, y2;

if (b == 0) {

*d = a, *x = 1, *y = 0;

return;

}

x2 = 1, x1 = 0, y2 = 0, y1 = 1;

#ifdef DEBUG

printf("------------------------------");

printf("-------------------\n");

printf("q r x y a b ");

printf("x2 x1 y2 y1\n");

printf("------------------------------");

printf("-------------------\n");

#endif

while (b > 0) {

q = a / b, r = a - q * b;

*x = x2 - q * x1, *y = y2 - q * y1;

a = b, b = r;

x2 = x1, x1 = *x, y2 = y1, y1 = *y;

#ifdef DEBUG

printf("%4ld %4ld %4ld %4ld ", q, r, *x, *y);

printf("%4ld %4ld %4ld %4ld ", a, b, x2, x1);

printf("%4ld %4ld\n", y2, y1);

#endif

}

*d = a, *x = x2, *y = y2;

#ifdef DEBUG

printf("------------------------------");

printf("-------------------\n");

#endif

}

long inverse(long a, long b)

/* returns the inverse of a modulo b if it exists 0 otherwise */

{

long d, x, y;

extended_euclid(a, b, &x, &y, &d);

if (d == 1) return x;

return 0;

}

long exp_mod(long x, long b, long n)

/* returns x ^ b mod n */

{

long a = 1, s = x;

while (b != 0) {

if (b & 1) a = (a * s) % n;

b >>= 1;

if (b != 0) s = (s * s) % n;

}

return a;

}

long square_root_mod(long a, long p)

/* returns the square root of a modulo an odd prime p

if it exists 0 otherwise */

{

long ai, b, c, d, e, i, r, s = 0, t = p - 1;

/* is a quadratic nonresidue */

if (JACOBI(a, p) == - 1) return 0;

/* find quadratic nonresidue */

do

do b = rand() % p; while (b == 0);

while (JACOBI(b, p) != - 1);

/* write p - 1 = 2 ^ s * t for odd t */

while (!(t & 1)) s++, t >>= 1;

ai = inverse(a, p);

c = exp_mod(b, t, p);

r = exp_mod(a, (t + 1) / 2, p);

for (i = 1; i < s; i++) {

e = exp_mod(2, s - i - 1, p);

d = exp_mod((r * r % p) * ai % p, e, p);

if (d == p - 1) r = r * c % p;

c = c * c % p;

}

return r;

}

int main(void)

{

long a, p;

printf("x ^ 2 = a mod p\n");

for (;;) {

printf("a or 0 to quit = ");

scanf("%ld", &a);

if (a == 0) break;

printf("p = ");

scanf("%ld", &p);

printf("square_root_mod(%ld, %ld) = %ld\n", a, p,

square_root_mod(a, p));

}

return 0;

}

3.44

Algorithm Finding square roots modulo n given its prime factors p

and q fsroots.c freelip (3,749)

/*

Author: Pate Williams (c) 1997

The following program determines the square

roots of a very long integer modulo a

composite very long integer n = p * q where

p and q are prime. See "Handbook of Applied

Cryptography" by Alfred J. Menezes et al

3.5.1 Section pages 100 - 101, 3.34 Algorithm

page 100 and 3.5.2 Section pages 101 - 102

3.44 Algorithm page 102.

*/

#include

#include

#include

#include

#include "lip.h"

void zsquare_root(verylong za, verylong zp, verylong *zr)

{

long i, s = 0, t;

verylong zb = 0, zc = 0, zd = 0, ze = 0, zi = 0;

verylong zq = 0, zs = 0, zt = 0, zx = 0, zy = 0;

if (zcompare(za, zp) < 0) zcopy(za, &ze);

else

zmod(za, zp, &ze);

if (zscompare(ze, 0l) == 0)

zzero(zr);

else if (zjacobi(ze, zp) == - 1)

zzero(zr);

else {

do

zrandomb(zp, &zb);

while (zscompare(zb, 0l) == 0 || zjacobi(zb, zp) != - 1);

zsadd(zp, - 1l, &zq);

zcopy(zq, &zy);

do {

zrshift(zy, 1l, &zt);

s++;

t = zodd(zt);

zcopy(zt, &zy);

} while (!t);

zinvmod(ze, zp, &zi);

zexpmod(zb, zt, zp, &zc);

zsadd(zt, 1l, &zs);

zrshift(zs, 1l, &zx);

zexpmod(ze, zx, zp, zr);

for (i = 1; i < s; i++) {

zsq(*zr, &zs);

zmulmod(zs, zi, zp, &zx);

zsexpmod(zx, pow(2, s - i - 1), zp, &zd);

if (zcompare(zd, zq) == 0) {

zmulmod(*zr, zc, zp, &zx);

zcopy(zx, zr);

}

zmulmod(zc, zc, zp, &zx);

zcopy(zx, &zc);

}

}

zfree(&zb);

zfree(&zc);

zfree(&zd);

zfree(&ze);

zfree(&zi);

zfree(&zq);

zfree(&zs);

zfree(&zt);

zfree(&zx);

}

void zsquare_roots(verylong za, verylong zp, verylong zq,

verylong *zx1, verylong *zx2,

verylong *zy1, verylong *zy2)

{

verylong zb = 0, zc = 0, zd = 0, ze = 0, zg = 0;

verylong zn = 0, zr = 0, zs = 0, zx = 0, zy = 0;

verylong zt = 0, zz = 0;

zsquare_root(za, zp, &zr);

if (zscompare(zr, 0l) != 0) {

zsqrtmod(za, zp, &zx);

assert(zcompare(zr, zx) == 0);

}

zsquare_root(za, zq, &zs);

if (zscompare(zs, 0l) != 0) {

zsqrtmod(za, zq, &zx);

assert(zcompare(zs, zx) == 0);

}

zexteucl(zp, &zc, zq, &zd, &zg);

if (zscompare(zg, 1l) == 0) {

zmul(zp, zq, &zn);

zmulmod(zr, zd, zn, &zb);

zmulmod(zb, zq, zn, &zt);

zmulmod(zs, zc, zn, &ze);

zmulmod(ze, zp, zn, &zz);

zaddmod(zt, zz, zn, &zx);

zmulmod(zr, zq, zn, &zb);

zmulmod(zs, zc, zn, &ze);

zmulmod(ze, zp, zn, &zz);

zsubmod(zt, zz, zn, &zy);

zmod(zx, zn, zx1);

znegate(&zx);

zmod(zx, zn, zx2);

zmod(zy, zn, zy1);

znegate(&zy);

zmod(zy, zn, zy2);

}

else {

zzero(zx1);

zzero(zx2);

zzero(zy1);

zzero(zy2);

}

zfree(&zb);

zfree(&zc);

zfree(&zd);

zfree(&ze);

zfree(&zg);

zfree(&zn);

zfree(&zr);

zfree(&zs);

zfree(&zt);

zfree(&zx);

zfree(&zy);

zfree(&zz);

}

int main(void)

{

char answer[256];

verylong za = 0, zp = 0, zq = 0, zu = 0, zv = 0;

verylong zx = 0, zy = 0;

do {

printf("enter the number whose square root is sought\n");

zread(&za);

printf("enter one of the modulus' prime factors\n");

zread(&zp);

printf("enter the other modulus prime factor\n");

zread(&zq);

zsquare_roots(za, zp, zq, &zu, &zv, &zx, &zy);

printf("the square roots modulo the composite number are:\n");

zwriteln(zu);

zwriteln(zv);

zwriteln(zx);

zwriteln(zy);

printf("compute another square root (n or y)? ");

scanf("%s", answer);

} while (tolower(answer[0]) == 'y');

zfree(&za);

zfree(&zp);

zfree(&zq);

zfree(&zu);

zfree(&zv);

zfree(&zx);

zfree(&zy);

return 0;

}

3.56

Algorithm Baby-step giant-step for computing discrete logarithms

dlp.c (5,234)

/*

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;

}

3.60

Algorithm Pollard's rho algorithm for computing discrete

logarithms dlp.c (5,234)

/*

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;

}

3.68

Algorithm Index-calculus algorithm for discrete logarithms in

cyclic groups index.c freelip (11,083)

/*

Author: Pate Williams (c) 1997

Index-calculus algorithm for computing discrete

logarithms. See "Handbook of Applied Cryptography"

by Alfred J. Menezes et al 3.6.5 Section 3.68

Algorithm pages 109 - 111. Also see 3.69 Example

pages 110 - 111.

*/

#include

#include

#include

#include

#include "lip.h"

#define BOUND 1000000l

#define CRT_SIZE 128l

#define DEBUG

struct node { long expon, prime; };

verylong **create_matrix(long m, long n)

{

long i;

verylong **zmatrix = calloc(m, sizeof(verylong *));

assert(zmatrix != 0);

for (i = 0; i < m; i++) {

zmatrix[i] = calloc(n, sizeof(verylong));

assert(zmatrix[i] != 0);

}

return zmatrix;

}

void delete_matrix(long m, long n, verylong **zmatrix)

{

long i, j;

for (i = 0; i < m; i++) {

for (j = 0; j < n; j++)

zfree(&zmatrix[i][j]);

free(zmatrix[i]);

}

free(zmatrix);

}

void zbinary_ext_gcd(verylong zx, verylong zy,

verylong *za, verylong *zb,

verylong *zv)

/* returns a * x + b * y = v, v = gcd(x, y) */

{

verylong zA = 0, zB = 0, zC = 0, zD = 0;

verylong zX = 0, zY = 0, zc = 0, zg = 0;

verylong zu = 0;

zone(&zg);

zcopy(zx, &zX);

zcopy(zy, &zY);

while (!zodd(zX) && !zodd(zY)) {

zrshift(zX, 1l, &zc);

zcopy(zc, &zX);

zrshift(zY, 1l, &zc);

zcopy(zc, &zY);

zlshift(zg, 1l, &zc);

zcopy(zc, &zg);

}

zcopy(zX, &zu);

zcopy(zY, zv);

zone(&zA);

zzero(&zB);

zzero(&zC);

zone(&zD);

do {

while (!zodd(zu)) {

zrshift(zu, 1l, &zc);

zcopy(zc, &zu);

if (!zodd(zA) && !zodd(zB)) {

zrshift(zA, 1l, &zc);

zcopy(zc, &zA);

zrshift(zB, 1l, &zc);

zcopy(zc, &zB);

}

else {

zadd(zA, zY, &zc);

zrshift(zc, 1l, &zA);

zsub(zB, zX, &zc);

zrshift(zc, 1l, &zB);

}

}

while (!zodd(*zv)) {

zrshift(*zv, 1l, &zc);

zcopy(zc, zv);

if (!zodd(zC) && !zodd(zD)) {

zrshift(zC, 1l, &zc);

zcopy(zc, &zC);

zrshift(zD, 1l, &zc);

zcopy(zc, &zD);

}

else {

zadd(zC, zY, &zc);

zrshift(zc, 1l, &zC);

zsub(zD, zX, &zc);

zrshift(zc, 1l, &zD);

}

}

if (zcompare(zu, *zv) >= 0) {

zsub(zu, *zv, &zc);

zcopy(zc, &zu);

zsub(zA, zC, &zc);

zcopy(zc, &zA);

zsub(zB, zD, &zc);

zcopy(zc, &zB);

}

else {

zsub(*zv, zu, &zc);

zcopy(zc, zv);

zsub(zC, zA, &zc);

zcopy(zc, &zC);

zsub(zD, zB, &zc);

zcopy(zc, &zD);

}

} while (zscompare(zu, 0l) != 0);

zcopy(zC, za);

zcopy(zD, zb);

zmul(zg, *zv, &zc);

zcopy(zc, zv);

zfree(&zA);

zfree(&zB);

zfree(&zC);

zfree(&zD);

zfree(&zX);

zfree(&zY);

zfree(&zc);

zfree(&zg);

zfree(&zu);

}

void zext_euclid(verylong za, verylong zb, verylong *zx,

verylong *zy, verylong *zd)

{

verylong zA = 0, zB = 0, zc = 0, zq = 0, zr = 0;

verylong zx1 = 0, zx2 = 0, zy1 = 0, zy2 = 0;

if (zscompare(zb, 0l) == 0) {

zone(zd);

zone(zx);

zzero(zy);

}

else {

zcopy(za, &zA);

zcopy(zb, &zB);

zone(&zx2);

zzero(&zx1);

zzero(&zy2);

zone(&zy1);

while (zscompare(zB, 0l) > 0) {

zdiv(zA, zB, &zq, &zr);

zmul(zq, zx1, &zc);

zsub(zx2, zc, zx);

zmul(zq, zy1, &zc);

zsub(zy2, zc, zy);

zcopy(zB, &zA);

zcopy(zr, &zB);

zcopy(zx1, &zx2);

zcopy(*zx, &zx1);

zcopy(zy1, &zy2);

zcopy(*zy, &zy1);

}

zcopy(zA, zd);

zcopy(zx2, zx);

zcopy(zy2, zy);

}

zfree(&zA);

zfree(&zB);

zfree(&zc);

zfree(&zq);

zfree(&zr);

zfree(&zx1);

zfree(&zx2);

zfree(&zy1);

zfree(&zy2);

}

void zinvmod_1(verylong zx, verylong zy, verylong *zi)

{

verylong zb = 0, zv = 0;

zext_euclid(zx, zy, zi, &zb, &zv);

if (zscompare(*zi, 0l) < 0) {

zadd(*zi, zy, &zb);

zcopy(zb, zi);

}

if (zscompare(zv, 1l) != 0) zzero(zi);

zfree(&zb);

zfree(&zv);

}

void gaussian_elimination(long m, long n, verylong zp,

verylong *zb, verylong *zx,

verylong **zm)

{

int found;

long i, j, k, l;

verylong zck = 0, zd = 0, zs = 0, zsum = 0, zt = 0;

for (j = 0; j < n; j++) {

found = 0, i = j;

while (!found && i < m) {

found = zscompare(zm[i][j], 0l) != 0;

if (found) {

zinvmod_1(zm[i][j], zp, &zd);

found = zscompare(zd, 0l) != 0;

}

if (!found) i++;

}

if (i > j) {

/* exchange colums */

for (l = j; l < n; l++) {

zcopy(zm[i][l], &zt);

zcopy(zm[j][l], &zm[i][l]);

zcopy(zt, &zm[j][l]);

}

zcopy(zb[i], &zt);

zcopy(zb[j], &zb[i]);

zcopy(zt, &zb[j]);

}

for (k = j + 1; k < m; k++) {

zmulmod(zd, zm[k][j], zp, &zck);

for (l = j + 1; l < n; l++) {

zmulmod(zck, zm[j][l], zp, &zt);

zsubmod(zm[k][l], zt, zp, &zsum);

zcopy(zsum, &zm[k][l]);

}

zmulmod(zck, zb[j], zp, &zt);

zsubmod(zb[k], zt, zp, &zsum);

zcopy(zsum, &zb[k]);

}

}

for (i = n - 1; i >= 0; i--) {

zzero(&zsum);

for (j = i + 1; j < n; j++) {

zmulmod(zm[i][j], zx[j], zp, &zt);

zaddmod(zt, zsum, zp, &zs);

zcopy(zs, &zsum);

}

zinvmod(zm[i][i], zp, &zd);

zsubmod(zb[i], zsum, zp, &zt);

zmulmod(zd, zt, zp, &zx[i]);

}

zfree(&zck);

zfree(&zd);

zfree(&zs);

zfree(&zsum);

zfree(&zt);

}

void Garner(long t, verylong *zm, verylong *zv, verylong *zx)

/* solution of the Chinese remaider theorem */

{

long i, j;

verylong za = 0, zb = 0, zu = 0, zC[CRT_SIZE];

for (i = 0; i < CRT_SIZE; i++) zC[i] = 0;

for (i = 1; i < t; i++) {

zone(&zC[i]);

for (j = 0; j 1) {

for (j = 0; j < k - 1; j++) {

temp = mu[k][j];

mu[k][j] = mu[l][j];

mu[l][j] = temp;

}

}

for (i = k + 1; i < n; i++) {

t = mu[i][k];

mu[i][k] = mu[i][l] - x * t;

mu[i][l] = t + mu[k][l] * mu[i][k];

}

k = max(1, k - 1);

goto L4;

}

for (l = k - 2; l >= 0; l--) Reduce(k, l, n, b, mu);

k++;

if (k < n) goto L4;

free_real_matrix(bs, n);

free_real_matrix(mu, n);

free_real_vector(B);

return 1;

}

int SubsetSum(long n, double s, double *a, double *x)

{

long n1 = n + 1;

double **b = allocate_real_matrix(n1, n1);

double sum;

long i, j, m = ceil(sqrt(n) / 2.0);

for (i = 0; i < n1; i++) {

if (i < n) {

for (j = 0; j < n1; j++) b[i][j] = 0.0;

b[i][i] = 1.0;

b[i][n1 - 1] = m * a[i];

}

else {

for (j = 0; j < n; j++) b[i][j] = 0.5;

b[i][n1 - 1] = m * s;

}

}

printf("the matrix to be reduced is:\n\n");

for (i = 0; i < n1; i++) {

for (j = 0; j < n1; j++)

printf("%6.2f ", b[i][j]);

printf("\n");

}

printf("\n");

if (!LLL(n1, b)) {

free_real_matrix(b, n1);

return 0;

}

printf("the reduced matrix is:\n\n");

for (i = 0; i < n1; i++) {

for (j = 0; j < n1; j++)

printf("%6.2f ", b[i][j]);

printf("\n");

}

printf("\n");

for (i = 0; i < n1; i++) {

for (j = 0; j < n; j++) x[j] = b[i][j] + 0.5;

sum = 0.0;

for (j = 0; j < n; j++) sum += a[j] * x[j];

if (sum == s) {

free_real_matrix(b, n1);

return 1;

}

for (j = 0; j < n; j++) x[j] = - b[i][j] + 0.5;

sum = 0.0;

for (j = 0; j < n; j++) sum += a[j] * x[j];

if (sum == s) {

free_real_matrix(b, n1);

return 1;

}

}

free_real_matrix(b, n1);

return 0;

}

int main(void)

{

long i, n = 8;

double *a = allocate_real_vector(n);

double *x = allocate_real_vector(n);

double s;

srand(time(NULL));

printf("\n");

for (i = 0; i < n; i++) a[i] = pow(2, i);

s = a[rand() % n] + a[rand() % n];

if (SubsetSum(n, s, a, x)) {

printf("sum: %f\n\n", s);

printf("x[i]\t\ta[i]\n\n");

for (i = 0; i < n; i++)

printf("%f\t%f\n", x[i], a[i]);

}

else printf("subset sum has no solution\n");

free_real_vector(a);

free_real_vector(x);

return 0;

}

3.108

Algorithm Finding a delta-quality simultaneous diophantine

approximation intlll.c (9,120)

/*

Author: Pate Williams (c) 1997

"Algorithm 2.6.7 (Integral LLL Algorithm). Given

a basis b[1], b[2],..., b[n] of a lattice (L, q)

by its gram matrix which is assumed to have inte-

gral coefficients, this algorithm transforms the

vectors b[i] so that when the algorithm terminates,

the b[i] form an LLL-reduced basis." -Henri Cohen-

See "A Course in Computational Algebraic Number

Theory" by Henri Cohen page 94. Also see "Handbook

of Applied Cryptography by Alfred J. Menezes et al

3.108 Algorithm "Finding a delta-quality simulta-

neous diophantine approximation" pages 121-122.

*/

#include

#include

#include

#include "lip.h"

void system_error(char error_message[])

{

fprintf(stderr, "%s", error_message);

exit(1);

}

verylong **allocate_very_matrix(long lr, long ur,

long lc, long uc)

{

/* Allocates a real matrix of range [lr..ur][lc..uc]. */

long i;

verylong **p = calloc((ur - lr + 1), sizeof(verylong *));

if (!p)

system_error("Failure in allocate_very_matrix().");

p -= lr;

for (i = lr; i