%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /data/down/eBOOKS/Handbook of Applied Cryptography/
Upload File :
Create Path :
Current File : //data/down/eBOOKS//Handbook of Applied Cryptography/garner.c

/*
  Author:  Pate Williams (c) 1997

  14.71 Algorithm Garner's Algorithm for CRT
  See "Handbook of Applied Cryptography" by
  Alfred J. Menezes et al page 612.
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "lip.h"

#define CRT_SIZE 8192l

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 <= i - 1; j++) {
      zinvmod(zm[j], zm[i], &zu);
      zmulmod(zu, zC[i], zm[i], &za);
      zcopy(za, &zC[i]);
    }
  }
  zcopy(zv[0], &zu);
  zcopy(zu, zx);
  for (i = 1; i < t; i++) {
    zsub(zv[i], *zx, &za);
    zmulmod(za, zC[i], zm[i], &zu);
    zone(&za);
    for (j = 0; j <= i - 1; j++) {
      zmul(za, zm[j], &zb);
      zcopy(zb, &za);
    }
    zmul(za, zu, &zb);
    zadd(*zx, zb, &za);
    zcopy(za, zx);
  }
  zfree(&za);
  zfree(&zb);
  zfree(&zu);
  for (i = 0; i < CRT_SIZE; i++) zfree(&zC[i]);
}

long OddRandom(long bit_length)
{
  long i, mask = 1, n;

  bit_length--;
  for (i = 1; i <= bit_length; i++)
    mask |= 1 << i;
  if (bit_length < 16)
    n = (1 << bit_length) | rand();
  else
    n = (1 << bit_length) | (rand() << 16) | rand();
  n &= mask;
  if ((n & 1) == 0) n++;
  return n;
}

void PROVABLE_PRIME(long k, verylong *zn)
{
  double c, r, s;
  int success;
  long B, m, n, p, sqrtn;
  verylong zI = 0, zR = 0, za = 0, zb = 0, zc = 0;
  verylong zd = 0, zk = 0, zl = 0, zq = 0, zu = 0;

  if (k <= 20) {
    do {
      n = OddRandom(k);
      sqrtn = sqrt(n);
      zpstart2();
      do p = zpnext(); while (n % p != 0 && p < sqrtn);
    } while (p < sqrtn);
    zintoz(n, zn);
  }
  else {
    c = 0.1;
    m = 20;
    B = c * k * k;
    if (k > 2 * m)
      do {
        s = rand() / (double) RAND_MAX;
        r = pow(2.0, s - 1.0);
      } while (k - r * k <= m);
    else
      r = 0.5;
    PROVABLE_PRIME(r * k + 1, &zq);
    zone(&za);
    zlshift(za, k - 1, &zk);
    zcopy(zq, &za);
    zlshift(za, 1l, &zl);
    zdiv(zk, zl, &zI, &za);
    zsadd(zI, 1l, &zl);
    zlshift(zI, 1l, &zu);
    success = 0;
    while (!success) {
      do zrandomb(zu, &zR); while (zcompare(zR, zl) < 0);
      zmul(zR, zq, &za);
      zlshift(za, 1l, &zb);
      zsadd(zb, 1l, zn);
      zcopy(zR, &za);
      zlshift(za, 1l, &zR);
      zpstart2();
      p = zpnext();
      while (zsmod(*zn, p) != 0 && p < B) p = zpnext();
      if (p >= B) {
        zcopy(*zn, &zc);
        zsadd(zc, - 2l, &zb);
        do
          zrandomb(*zn, &za);
        while (zscompare(za, 2l) < 0 || zcompare(za, zb) > 0);
        zsadd(*zn, - 1l, &zc);
        zexpmod(za, zc, *zn, &zb);
        if (zscompare(zb, 1l) == 0) {
          zexpmod(za, zR, *zn, &zb);
          zcopy(zb, &zd);
          zsadd(zd, - 1l, &zb);
          zgcd(zb, *zn, &zd);
          success = zscompare(zd, 1l) == 0;
        }
      }
    }
  }
  zfree(&zI);
  zfree(&zR);
  zfree(&za);
  zfree(&zb);
  zfree(&zc);
  zfree(&zd);
  zfree(&zk);
  zfree(&zl);
  zfree(&zq);
  zfree(&zu);
}

void RSA_gen_keys(long length, verylong *zd,
                  verylong *ze, verylong *zp,
                  verylong *zq)
{
  verylong zp1 = 0, zq1 = 0;
  verylong zphi = 0, zx = 0;

  srand(time(NULL));
  zrstarts(time(NULL));
  PROVABLE_PRIME(length, zp);
  PROVABLE_PRIME(length, zq);
  zsadd(*zp, - 1l, &zp1);
  zsadd(*zq, - 1l, &zq1);
  zmul(zp1, zq1, &zphi);
  do {
    do zrandomb(zphi, ze); while (zscompare(*ze, 1l) <= 0);
    zgcd(*ze, zphi, &zx);
  } while (zscompare(zx, 1l) != 0);
  zinvmod(*ze, zphi, zd);
  zfree(&zp1);
  zfree(&zq1);
  zfree(&zphi);
  zfree(&zx);
}

void RSA_exponentiation(verylong zx, verylong zd,
                        verylong zp, verylong zq,
                        verylong *zM)
{
  verylong zdp = 0, zdq = 0, zp1 = 0, zq1 = 0;
  verylong zm[2], zv[2];

  zsadd(zp, - 1l, &zp1);
  zsadd(zq, - 1l, &zq1);
  zmod(zd, zp1, &zdp);
  zmod(zd, zq1, &zdq);
  zm[0] = zm[1] = zv[0] = zv[1] = 0;
  zcopy(zp, &zm[0]);
  zcopy(zq, &zm[1]);
  zexpmod(zx, zdp, zp, &zv[0]);
  zexpmod(zx, zdq, zq, &zv[1]);
  Garner(2l, zm, zv, zM);
  zfree(&zdp);
  zfree(&zdq);
  zfree(&zp1);
  zfree(&zq1);
  zfree(&zm[0]);
  zfree(&zm[1]);
  zfree(&zv[0]);
  zfree(&zv[1]);
}

int main(void)
{
  verylong zM = 0, zN = 0, zd = 0, ze = 0, zn = 0;
  verylong zp = 0, zq = 0, zx = 0;

  RSA_gen_keys(128l, &zd, &ze, &zp, &zq);
  zintoz(65537l, &zx);
  RSA_exponentiation(zx, zd, zp, zq, &zM);
  zmul(zp, zq, &zn);
  zexpmod(zx, zd, zn, &zN);
  if (zcompare(zM, zN) == 0)
    printf("RSA_exponentiation confirmed\n");
  else
    printf("*error*\nin RSA_exponentiation\n");
  zfree(&zM);
  zfree(&zN);
  zfree(&zd);
  zfree(&ze);
  zfree(&zn);
  zfree(&zp);
  zfree(&zq);
  zfree(&zx);
  return 0;
}

Zerion Mini Shell 1.0