what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

elliptic.src

elliptic.src
Posted Dec 21, 1999

elliptic.src

tags | encryption
SHA-256 | d410b62690aefd2d1b231f503529a0d65fc7160e23b3180786aeea9eaf292a75

elliptic.src

Change Mirror Download
/******    bigint.h   *****/
/****************************************************************
* *
* defines and structures for crypto section. *
* Jan. 21, 1995 *
* *
****************************************************************/

#define WORDSIZE 32
/*#define MAXBITS 1024*/
#define MAXBITS 256
#define MAXLONG (MAXBITS/WORDSIZE)
#define SUBMASK 0x80000000
#define LONGPOS (MAXLONG-1)
#define MAXSHIFT (WORDSIZE-1)
/*#define field_prime 1019
#define log2_fp 9
/* that's the most significant power of 2, or floor(log2(field_prime)) */
#define field_prime 149
#define log2_fp 7
/*#define field_prime 13
#define log2_fp 3 */
#define NUMBITS (field_prime-1)
#define NUMWORD (NUMBITS/WORDSIZE)
#define UPRSHIFT (NUMBITS%WORDSIZE)
#define UPRBIT (1L<<(UPRSHIFT-1))
#define STRTPOS (LONGPOS-NUMWORD)
#define UPRMASK (~(-1L<<UPRSHIFT))

typedef short int INDEX;
typedef unsigned long ELEMENT;
typedef struct {
ELEMENT b[MAXLONG];
} BIGINT;

/****** eliptic.h *****/
/****************************************************************
* *
* These are structures used to create elliptic curve *
* points and parameters. "form" is a just a fast way to check *
* if a2 == 0. *
* form equation *
* *
* 0 y^2 + xy = x^3 + a_6 *
* 1 y^2 + xy = x^3 + a_2*x^2 + a_6 *
* *
****************************************************************/

typedef struct {
INDEX form;
BIGINT a2;
BIGINT a6;
} CURVE;

/* projective coordinates for a point */

typedef struct {
BIGINT x;
BIGINT y;
BIGINT z;
} POINT;

/* started getting tired of writing this */

#define SUMLOOP(i) for(i=STRTPOS; i<MAXLONG; i++)

/****** eliptic_keys.h *****/
/* higher level structures to manipulate elliptic curve public keys */

#define MAX_NAME_SIZE 64
#define MAX_PHRASE_SIZE 256

typedef struct {
POINT p;
POINT q;
CURVE crv;
char name[MAX_NAME_SIZE];
char address[MAX_NAME_SIZE];
} PUBKEY;

/****** bigint.c *****/
/************************************************************************
* *
* Routines to implement optimal normal basis multiplication. *
* See Mullin, Onyszchuk, Vanstone, Wilson, "Optimal Normal Bases in *
* GF(p^n)", Discrete Applied Math, V22, 1988, p149 *
* Ash, Blake, Vanstone, "Low Complexity Normal Bases", Discrete *
* Applied Math, V25, 1989, p191 *
* Agnew, Mullin, Onyszchuk, Vanstone, "An Implementation for a Fast *
* Public-Key Cryptosystem", Jour. Cryptology, 1991, V3, p 63 *
* "Elliptic Curve Public Key Cryptosystems", A. Menezes, Kluwer, 1993 *
* pages 83-86. *
* *
* Jan. 22, 1995 *
* *
************************************************************************/

#include <stdio.h>
#include "bigint.h"

/* global structure for all multiply routines. compute once at begining
to save disk space. */

INDEX Lambda[field_prime]; /* for multiply */
ELEMENT mask_table[WORDSIZE]; /* for shift_index */

/* shift routines assume bigendian structure. operate in place */

void shift_left(a)
BIGINT *a;
{
register INDEX i;
register ELEMENT bit,temp;

bit = 0;
for (i=LONGPOS; i>=STRTPOS; i--) {
temp = ( a->b[i] << 1) | bit;
bit = (a->b[i] & SUBMASK) ? 1L : 0L;
a->b[i] = temp;
}
a->b[STRTPOS] &= UPRMASK;
}

void shift_right(a)
BIGINT *a;
{
register INDEX i;
register ELEMENT bit,temp;

bit = (a->b[STRTPOS] & 1) ? SUBMASK : 0;
for (i=STRTPOS; i< MAXLONG; i++) {
temp = ( a->b[i] >> 1) | bit;
bit = (a->b[i] & 1) ? SUBMASK : 0;
a->b[i] = temp;
}
}

/* an entirely different way to do the same thing */
void rot_left(a)
BIGINT *a;
{
register INDEX i;
register ELEMENT bit,temp;

bit = (a->b[STRTPOS] & UPRBIT) ? 1L : 0L;
for (i=LONGPOS; i>=STRTPOS; i--) {
temp = (a->b[i] & SUBMASK) ? 1L : 0L;
a->b[i] = ( a->b[i] << 1) | bit;
bit = temp;
}
a->b[STRTPOS] &= UPRMASK;
}

void rot_right(a)
BIGINT *a;
{
register INDEX i;
register ELEMENT bit,temp;

bit = (a->b[LONGPOS] & 1) ? UPRBIT : 0L;
for (i=STRTPOS; i< MAXLONG; i++) {
temp = ( a->b[i] >> 1) | bit;
bit = (a->b[i] & 1) ? SUBMASK : 0L;
a->b[i] = temp;
}
a->b[STRTPOS] &= UPRMASK;
}

void null(a)
BIGINT *a;
{
register INDEX i;

for (i=0; i<MAXLONG; i++) a->b[i] = 0;
}

void copy (a,b)
BIGINT *a,*b;
{
register INDEX i;

for (i=0; i<MAXLONG; i++) b->b[i] = a->b[i];
}

/* create Lambda [i,j] table. indexed by j, each entry contains the
value of i which satisfies 2^i + 2^j = 1 || 0 mod field_prime. There are
two 16 bit entries per index j except for zero. See references for
details. Since 2^0 = 1 and 2^2n = 1, 2^n = -1 and the first entry would
be 2^0 + 2^n = 0. Multiplying both sides by 2, it stays congruent to
zero. So Half the table is unnecessary since multiplying exponents by
2 is the same as squaring is the same as rotation once. Lambda[0] stores
n = (field_prime - 1)/2. The terms congruent to one must be found via
lookup in the log table. Since every entry for (i,j) also generates an
entry for (j,i), the whole 1D table can be built quickly.
*/

void genlambda()
{
INDEX i,logof,n,index;
INDEX log2[field_prime],twoexp;

for (i=0; i<field_prime; i++) log2[i] = -1;

/* build antilog table first */

twoexp = 1;
for (i=0; i<field_prime; i++) {
log2[twoexp] = i;
twoexp = (twoexp << 1) % field_prime;
}

/* compute n for easy reference */

n = (field_prime - 1)/2;
Lambda[0] = n;
Lambda[1] = n;
Lambda[n] = 1;

/* loop over result space. Since we want 2^i + 2^j = 1 mod field_prime
it's a ton easier to loop on 2^i and look up i then solve the silly
equations. Think about it, make a table, and it'll be obvious. */

for (i=2; i<=n; i++) {
index = log2[i];
logof = log2[field_prime - i + 1];
Lambda[index] = logof;
Lambda[logof] = index;
}
/* last term, it's the only one which equals itself. See references. */

Lambda[log2[n+1]] = log2[n+1];
}

/* for use with multiply routine. indexed rotation uses:
a is source
b is destination
amount is bit position which gets moved to zero bit
For the moment, starting with rotations if shift amount is same
size as first or last words. May want to divide that by 2
depending on how slow shift is compared with bit chunk mover.
Bit chunk mover needs mask table, which should be built during
initialization.
*/

void initmask()
{
register INDEX i;

mask_table[0] = -1L;
for (i=1; i<WORDSIZE; i++) mask_table[i] = (ELEMENT)~(-1L << i);
}

void shift_index(src,dst,amount)
BIGINT *src,*dst;
INDEX amount;
{
INDEX srcptr, srcstrt, srcwrd, limit;
INDEX dstptr, dststrt, dstwrd, bitsmvd, strt;
ELEMENT temp, mask;
INDEX srcbits, dstbits, shift;

null(dst);

/* first determine if simple rotation is worth doing. This could use
some tuning, depending on processor, bus time, etc.
*/
limit = 3;
if ((amount < limit) || (amount > (NUMBITS - limit))){
copy(src,dst);
if (! amount) return;
if (amount < limit) {
while (amount) {
rot_right(dst);
amount--;
}
} else {
while (amount < NUMBITS) {
rot_left(dst);
amount++;
}
}
return;
}

/* rather than move every word amount times, try and only read it 2 or 3 and
put each sub component in the right place.
*/

/* initialize bit pointers */

srcptr = amount;
dstptr = 0;

/* scan at bit level */

while (dstptr < NUMBITS) {

/* find word offsets into bigint array */

srcwrd = LONGPOS - srcptr/WORDSIZE;
dstwrd = LONGPOS - dstptr/WORDSIZE;

/* locate starting bit positions within each ELEMENT */

srcstrt = srcptr % WORDSIZE;
dststrt = dstptr % WORDSIZE;

/* smallest value determines maximum bits that can be moved */

srcbits = (srcwrd == STRTPOS) ? UPRSHIFT - srcstrt
: WORDSIZE - srcstrt;
dstbits = (dstwrd == STRTPOS) ? UPRSHIFT - dststrt
: WORDSIZE - dststrt;
bitsmvd = (srcbits < dstbits) ? srcbits : dstbits;

/* max bits set in zero index of mask_table, then adjust mask over
result and compute source shift amount. */

bitsmvd %= WORDSIZE;
mask = mask_table[bitsmvd] << dststrt;
temp = src->b[srcwrd];
shift = abs(srcstrt - dststrt);

/* create result, or into place */

if (dststrt < srcstrt)
temp = (temp >> shift) & mask;
else
temp = (temp << shift) & mask;
dst->b[dstwrd] |= temp;

/* bump source cyclicly, destination linearly */

if (!bitsmvd) bitsmvd = WORDSIZE;
srcptr = (srcptr + bitsmvd) % NUMBITS;
dstptr = (dstptr + bitsmvd);
} /* until dstptr >= NUMBITS */
}

/* Normal Basis Multiplication. Assumes Lambda vector already initialized
for type 1 normal basis. See above references for details
Output = c = a*b over GF(2^NUMBITS)
*/

void opt_mul(a,b,c)
BIGINT *a,*b,*c;
{
register INDEX i,j;
BIGINT a1,a2,bcopy;

null(c);
copy(b,&bcopy);

/* for each rotation of B vector there are at most two rotations of A vector
in a type 1 normal basis. Lambda is lookup table of A rotations from 2^i +
2^j = 1 mod field_prime. For 2^i + 2^j = 0, need only one master shift and
single rotations thereafter. The Lambda table is uniformly scrambled and
shows why this is an efficient bit mixing algorithm.
*/

shift_index(a,&a1,Lambda[0]);
for (i=STRTPOS; i<MAXLONG; i++)
c->b[i] = bcopy.b[i] & a1.b[i];

/* main loop, two lookups for every position */

for (j=1; j<NUMBITS; j++) {
rot_right(&bcopy);
rot_right(&a1);
shift_index(a,&a2,Lambda[j]);
for (i=STRTPOS; i<MAXLONG; i++) {
/* c->b[i] ^= b->b[i] & (a1.b[i] ^ a2.b[i]);
expression too complex!!??!! */
a2.b[i] ^= a1.b[i];
a2.b[i] &= bcopy.b[i];
c->b[i] ^= a2.b[i];
}
}
}

/* opt_inv computes the inverse of a normal basis, GF(2^n) "number".
Enter with pointers to source number, destination storage,
Lambda table and mask_table. Leaves source alone and puts its inverse
into destination. The algorithm is based on the explanation given in
Menezes book. the bit pattern of n-1 determines the number of multiplies.
a sliding window starting from msb determines the power of 2 (shift index)
and the next bit determines the number of multiplies for that power.
Seems pretty cool to this programmer!
*/

void opt_inv(src,dst)
BIGINT *src, *dst;
{
INDEX m, x, y, bitpos;
BIGINT ap1,ap2;

copy(src, &ap1);
null(dst);
m = field_prime - 2; /* = NUMBITS - 1 */
bitpos = log2_fp;

x = m >> bitpos;
if (x != 1) {
printf("Error attempting to compute inverse!!\n");
printf("x=%d m=%d bitpos=%d\n",x,m,bitpos);
return;
}
while (x < m) {
bitpos--;
y = m >> bitpos;
shift_index( &ap1, &ap2, NUMBITS-x);
opt_mul( &ap1, &ap2, dst);
if (y & 1) {
rot_left(dst); /* this squares destination */
opt_mul( src, dst, &ap1);
} else
copy(dst, &ap1);
x = y;
}
rot_left( &ap1); /* final squaring */
copy (&ap1,dst);
}

void init_opt_math()
{

initmask(); /* create shift_index mask table */
genlambda(); /* create Lambda pointer table */
}

/****** eliptic.c *****/
/************************************************************************
* *
* Elliptic curves over Galois Fields. These routines find points *
* on a curve, add and double points for type 1 optimal normal bases. *
* *
* For succint explanaition, see Menezes, page 92 *
* *
************************************************************************/

#include <stdio.h>
#include "bigint.h"
#include "eliptic.h"

/************************************************************************
* Note that the following is obvious to mathematicians. I thought it *
* was pretty cool when I discovered it myself, <sigh>. *
* *
* Routine to solve quadradic equation. Enter with coeficients *
* a and b and it returns solutions y[2]: y^2 + ay + b = 0. *
* If Tr(b/a^2) != 0, returns y=0 and error code 1. *
* If Tr(b/a^2) == 0, returns y[2] and error code 0. *
* If solution fails, returns y=0 and error code 2. *
* *
* Algorithm used based on normal basis GF math. Since (a+b)^2 = *
* a^2 + b^2 it follows that (a+b)^.5 = a^.5 + b^.5. Note that squaring*
* is a left shift and rooting is a right shift in a normal basis. *
* Transforming the source equation with y = ax and dividing by a^2 *
* gives: *
* x^2 + x + b/a^2 = 0 *
* *
* or x = x^.5 + (b/a^2)^.5 *
* *
* Let k_i = the ith significant bit of (b/a^2)^.5 and *
* x_i = the ith significant bit of x. *
* The above equation is equivelent to a bitwise representation as *
* *
* x_i = x_(i+1) + k_i *
* or *
* x(i+1) = x_i + k_i. *
* *
* Since both x and x+1 are solutions, and 1 is represented by all *
* bits set in a normal basis, we can start with x_0 = 0 or 1 at our *
* pleasure and use the recursion relation to discover every bit of x. *
* The answer is then ax and ax+a returned in y[0] and y[1] respectively*
* If the sum of x_(n-1) + k_(n-1) != x_0, returns error code 2 and *
* y = 0. *
* *
* error code returns *
* 0 y[0] and y[1] values *
* 1 y[0] = y[1] = 0 *
* 2 mathematicly impossible !!!! *
* *
************************************************************************/

extern ELEMENT mask_table[WORDSIZE];
extern opt_inv(), rot_left(), rot_right(), null(), opt_mul();
extern big_print(),copy();

int gf_quadradic(a, b, y)
BIGINT *a, *b, *y;
{
INDEX i, l, bits;
BIGINT x, k, a2;
ELEMENT r, t, mask;

/* test for b=0. Won't work if it is. */

l = 1;
for (i=STRTPOS; i<MAXLONG; i++) {
if (b->b[i] == 0) continue;
else {
l = 0;
break;
}
}
if (l) {
null(&y[0]);
null(&y[1]);
return(1);
}

/* find a^-2 */

opt_inv( a, &a2);
rot_left(&a2);

/* find k=(b/a^2)^.5 */

opt_mul( b, &a2, &k);
rot_right(&k);
r = 0;

/* check that Tr(k) is zero. Combine all words first. */

for (i=STRTPOS; i<MAXLONG; i++)
r ^= k.b[i];

/* take trace of word, combining half of all the bits each time */

for (bits = WORDSIZE/2; bits > 0; bits /= 2)
r = ((r & mask_table[bits]) ^ (r >> bits));

/* if not zero, return error code 1. */

if (r) {
null(&y[0]);
null(&y[1]);
return(1);
}

/* point is valid, proceed with solution. mask points to bit i,
which is known, in x bits previously found and k (=b/a^2). */

null(&x);
mask = 1;
for (bits=0; bits < NUMBITS ; bits++) {

/* source long word could be different than destination */

i = LONGPOS - bits/WORDSIZE;
l = LONGPOS - (bits + 1)/WORDSIZE;

/* use present bits to compute next one */

r = k.b[i] & mask;
t = x.b[i] & mask;
r ^= t;

/* same word, so just shift result up */

if ( l == i ) {
r <<= 1;
x.b[l] |= r;
mask <<= 1;
} else {

/* different word, reset mask and use a 1 */

mask = 1;
if (r) x.b[l] = 1;
}
}

/* test that last bit generates a zero */

r = k.b[STRTPOS] & UPRBIT;
t = x.b[STRTPOS] & UPRBIT;
if ( r^t ) {
null(&y[0]);
null(&y[1]);
return(2);
}

/* convert solution back via y = ax */

opt_mul(a, &x, &y[0]);

/* and create complementary soultion y = ax + a */

null (&y[1]);
for (i = STRTPOS; i < MAXLONG; i++)
y[1].b[i] = y[0].b[i] ^ a->b[i];

/* no errors, bye! */

return(0);
}

/* compute R.H.S. f(x) = x^3 + a2*x^2 + a6
curv.form = 0 implies a2 = 0, so no extra multiply.
curv.form = 1 is the "twist" curve.
*/

fofx(x, curv, f)
BIGINT *x, *f;
CURVE *curv;
{

BIGINT x2,x3;
INDEX i;

copy(x, &x2);
rot_left(&x2);
opt_mul(x, &x2, &x3);
if (curv->form) opt_mul(&x2, &curv->a2, f);
else null(f);
for (i = STRTPOS; i < MAXLONG; i++)
f->b[i] ^= (x3.b[i] ^ curv->a6.b[i]);
}

/****************************************************************************
* *
* Implement elliptic curve point addition for optimal normal basis form. *
* Enter with pointers to p1, p2, p3 and curve data for E. Computes *
* p3 = p1 + p2 in projective coordinates over curve E. See Menezes *
* "Elliptic Curve Public Key Cryptosystems." *
* Had to derive this several times to get it correct. Menezes form not *
* generic for both p1 and p2 being arbitrary projections. *
* Note that this is not optimized to minimize multiplies, but to follow *
* the math easier. *
****************************************************************************/

esum (p1, p2, p3, curv)
POINT *p1, *p2, *p3;
CURVE *curv;
{
INDEX i;
BIGINT x1z2, y1z2, z1z2, x2z1, y2z1;
BIGINT A, B, AplusB, Bsqr, C, D, E;
BIGINT temp1, temp2;

/* start with basic building blocks */

opt_mul (&p1->x, &p2->z, &x1z2);
opt_mul (&p1->y, &p2->z, &y1z2);
opt_mul( &p1->z, &p2->z, &z1z2); /* z_1 * z_2 */
opt_mul (&p2->x, &p1->z, &x2z1);
opt_mul (&p2->y, &p1->z, &y2z1);

/* find terms A and B */

SUMLOOP(i) {
B.b[i] = x1z2.b[i] ^ x2z1.b[i];
A.b[i] = y1z2.b[i] ^ y2z1.b[i];
}

/* Next group of terms A+B and B^2 */

SUMLOOP(i) AplusB.b[i] = A.b[i] ^ B.b[i];
copy( &B, &Bsqr);
rot_left( &Bsqr);

/* set up term C. No multiply if a2 = 0 */

copy( &B, &C);
if (curv->form) {
opt_mul(&curv->a2, &z1z2, &temp1);
SUMLOOP(i) C.b[i] ^= temp1.b[i];
}

/* main term for x3, also used in y3 (D in Menezes book) */

opt_mul(&A, &AplusB, &temp1);
opt_mul(&z1z2, &temp1, &temp2);
opt_mul(&Bsqr, &C, &D);
SUMLOOP(i) D.b[i] ^= temp2.b[i];

/* compute x3 */

opt_mul( &B, &D, &p3->x);

/* compute z3 */

opt_mul( &z1z2, &B, &temp1);
opt_mul(&Bsqr, &temp1, &p3->z);

/* next major term for y */

opt_mul( &x1z2, &A, &temp1);
opt_mul( &y1z2, &B, &E);
SUMLOOP(i) E.b[i] ^= temp1.b[i];

/* finally compute y3 */

opt_mul( &AplusB, &D, &temp1);
opt_mul( &Bsqr, &E, &temp2);
SUMLOOP(i) p3->y.b[i] = temp1.b[i] ^ temp2.b[i];
}

/* elliptic curve doubling routine for projective coordinates over normal
basis. Enter with p1, p3 as source and destination as well as curv
to operate on. Returns p3 = 2*p1.
*/

edbl (p1, p3, curv)
POINT *p1, *p3;
CURVE *curv;
{
BIGINT x1z1, x14, termd, temp1, temp2;
INDEX i;

opt_mul( &p1->x, &p1->z, &x1z1);
copy(&p1->x, &x14); /* x_1 ^ 4 */
rot_left( &x14);
rot_left( &x14);
copy(&p1->z, &termd); /* z_1 ^ 4 */
rot_left ( &termd);
rot_left ( &termd);
opt_mul ( &termd, &curv->a6, &temp1);
SUMLOOP(i) termd.b[i] = x14.b[i] ^ temp1.b[i]; /* D = x1^4 + a6*z1^4 */

/* now compute results */

opt_mul ( &termd, &x1z1, &p3->x);
copy ( &x1z1, &temp1);
rot_left( &temp1);
opt_mul ( &temp1, &x1z1, &p3->z); /* z3 = A^3 */
opt_mul ( &x1z1, &x14, &p3->y); /* x1^5 * z1 */
copy ( &p1->x, &temp1);
rot_left( &temp1); /* x1 ^ 2 */
opt_mul ( &p1->y, &p1->z, &temp2); /* y1 * z1 */
SUMLOOP(i) {
temp2.b[i] ^= temp1.b[i]; /* proto sum for D */
p3->y.b[i] ^= p3->x.b[i]; /* first 2 terms of y3 found */
}
opt_mul ( &termd, &temp2, &temp1); /* do multiply */
SUMLOOP(i) p3->y.b[i] ^= temp1.b[i]; /* and finish y3 */
}

/* subtract two points on a curve. just negates p2 and does a sum.
Returns p3 = p1 - p2 over curv.
*/

esub (p1, p2, p3, curv)
POINT *p1, *p2, *p3;
CURVE *curv;
{
POINT negp;
INDEX i;

copy ( &p2->x, &negp.x);
null (&negp.y);
SUMLOOP(i) negp.y.b[i] = p2->x.b[i] ^ p2->y.b[i];
copy ( &p2->z, &negp.z);
esum (p1, &negp, p3, curv);
}

/* need to move points around, not just values. Optimize later. */

void copy_point (p1, p2)
POINT *p1, *p2;
{
copy (&p1->x, &p2->x);
copy (&p1->y, &p2->y);
copy (&p1->z, &p2->z);
}

/* Routine to compute kP where k is an integer (base 2, not normal basis)
and P is a point on an elliptic curve. This routine assumes that K
is representable in the same bit field as x, y or z values of P.
This is for simplicity, larger or smaller fields can be independently
implemented.
Enter with: integer k, source point P, curve to compute over (curv) and
Returns with: result point R.

Reference: Koblitz, "CM-Curves with good Cryptografic Properties",
Springer-Verlag LNCS #576, p279 (pg 284 really), 1992
*/
ELEMENT bit_table[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256,
0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000,
0x10000, 0x20000, 0x40000, 0x80000,
0x100000, 0x200000, 0x400000, 0x800000,
0x1000000, 0x2000000, 0x4000000, 0x8000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000 };

void elptic_mul(k, p, r, curv)
BIGINT *k;
POINT *p, *r;
CURVE *curv;
{
char blncd[NUMBITS+1];
ELEMENT wordptr, bit_count, mskindx, sequnce;
POINT temp;

/* scan across k from right to left to expand bits to chars */

for (bit_count = 0; bit_count < NUMBITS; bit_count++) {
wordptr = LONGPOS - bit_count/WORDSIZE;
mskindx = bit_count % WORDSIZE;
if (k->b[wordptr] & bit_table[mskindx]) blncd[bit_count] = 1;
else blncd[bit_count] = 0;
}
blncd[NUMBITS] = 0;

/* Next convert balanced array to ballanced representation */
/* sequence flag used for multiple 1's being switched to 0's. */

sequnce = 0;
bit_count = 0;
while (bit_count <= NUMBITS) {
if ( blncd[bit_count]) {
if (sequnce) /* in middle of 1's sequence */
blncd[bit_count] = 0;
else if (blncd[bit_count+1]) {
sequnce = 1; /* next bit also set, begin sequnce */
blncd[bit_count] = -1;
}
bit_count++;
} else {
if (sequnce) { /* last bit of sequence */
blncd[bit_count] = 1;
sequnce = 0;
} else
bit_count++;
}
}

/* now follow ballanced representation and compute kP */

bit_count = NUMBITS;
while (!blncd[bit_count] && bit_count >= 0) bit_count--; /* find first bit */
if (bit_count < 0) {
null (&r->x);
null (&r->y);
null (&r->z);
return;
}
copy_point(p,r); /* first bit always set */
while (bit_count > 0) {
edbl(r, &temp, curv);
bit_count--;
switch (blncd[bit_count]) {
case 1: esum (p, &temp, r, curv);
break;
case -1: esub (&temp, p, r, curv);
break;
case 0: copy_point (&temp, r);
}
}
}

/* One is not what it appears to be. In any normal basis, "1" is the sum of
all powers of the generator. So this routine puts ones to fill the number size
being used in the address of the BIGINT supplied. */

void one (place)
BIGINT *place;
{
INDEX i;

SUMLOOP(i) place->b[i] = -1L;
place->b[STRTPOS] &= UPRMASK;
}

/* This routine "flatens" a projective 3D point back to the 2D plane. */

void flaten (point)
POINT *point;
{
POINT invers;

opt_inv( &point->z, &invers.z);
opt_mul( &invers.z, &point->x, &invers.x);
opt_mul( &invers.z, &point->y, &invers.y);
copy (&invers.x, &point->x);
copy (&invers.y, &point->y);
one(&point->z);
}

/****** support.c *****/
/* Simple support functions for elliptic curve data manipulation */

#include <stdio.h>
#include <strings.h>
#include "bigint.h"
#include "eliptic.h"
#include "eliptic_keys.h"

extern void init_opt_math();
extern gf_quadradic( BIGINT*, BIGINT*, BIGINT*);
extern void fofx( BIGINT*, CURVE*, BIGINT*);
extern void copy( BIGINT*, BIGINT*);
extern void null( BIGINT*);
extern void elptic_mul(BIGINT*, POINT*, POINT*, CURVE*);
extern void opt_inv(BIGINT*, BIGINT*);
extern void edbl(POINT*, POINT*, CURVE*);
extern void esum(POINT*, POINT*, POINT*, CURVE*);
extern void esub(POINT*, POINT*, POINT*, CURVE*);
extern void one( BIGINT*);
extern void flaten( POINT*);
extern ELEMENT bit_table[WORDSIZE];

/* random seed is accessable to everyone, not best way, but functional. */

unsigned long random_seed;

/* below is from Mother code, till end of mother. Above is all my fault. */

#include <string.h>

static short mother1[10];
static short mother2[10];
static short mStart=1;

#define m16Long 65536L /* 2^16 */
#define m16Mask 0xFFFF /* mask for lower 16 bits */
#define m15Mask 0x7FFF /* mask for lower 15 bits */
#define m31Mask 0x7FFFFFFF /* mask for 31 bits */
#define m32Double 4294967295.0 /* 2^32-1 */

/* Mother **************************************************************
| George Marsaglia's The mother of all random number generators
| producing uniformly distributed pseudo random 32 bit values with
| period about 2^250.
|
| The arrays mother1 and mother2 store carry values in their
| first element, and random 16 bit numbers in elements 1 to 8.
| These random numbers are moved to elements 2 to 9 and a new
| carry and number are generated and placed in elements 0 and 1.
| The arrays mother1 and mother2 are filled with random 16 bit values
| on first call of Mother by another generator. mStart is the switch.
|
| Returns:
| A 32 bit random number is obtained by combining the output of the
| two generators and returned in *pSeed. It is also scaled by
| 2^32-1 and returned as a double between 0 and 1
|
| SEED:
| The inital value of *pSeed may be any long value
|
| Bob Wheeler 8/8/94
|
| removed double return since I don't need it.
*/


void Mother(unsigned long *pSeed)
{
unsigned long number,
number1,
number2;
short n,
*p;
unsigned short sNumber;

/* Initialize motheri with 9 random values the first time */
if (mStart) {
sNumber= *pSeed&m16Mask; /* The low 16 bits */
number= *pSeed&m31Mask; /* Only want 31 bits */

p=mother1;
for (n=18;n--;) {
number=30903*sNumber+(number>>16);
/* One line multiply-with-cary */
*p++=sNumber=number&m16Mask;
if (n==9)
p=mother2;
}
/* make cary 15 bits */
mother1[0]&=m15Mask;
mother2[0]&=m15Mask;
mStart=0;
}

/* Move elements 1 to 8 to 2 to 9 */
memmove(mother1+2,mother1+1,8*sizeof(short));
memmove(mother2+2,mother2+1,8*sizeof(short));

/* Put the carry values in numberi */
number1=mother1[0];
number2=mother2[0];

/* Form the linear combinations */

number1+=1941*mother1[2]+1860*mother1[3]+1812*mother1[4]+1776*mother1[5]+
1492*mother1[6]+1215*mother1[7]+1066*mother1[8]+12013*mother1[9];

number2+=1111*mother2[2]+2222*mother2[3]+3333*mother2[4]+4444*mother2[5]+
5555*mother2[6]+6666*mother2[7]+7777*mother2[8]+9272*mother2[9];

/* Save the high bits of numberi as the new carry */
mother1[0]=number1/m16Long;
mother2[0]=number2/m16Long;
/* Put the low bits of numberi into motheri[1] */
mother1[1]=m16Mask&number1;
mother2[1]=m16Mask&number2;

/* Combine the two 16 bit random numbers into one 32 bit */
*pSeed=(((long)mother1[1])<<16)+(long)mother2[1];

/* Return a double value between 0 and 1
return ((double)*pSeed)/m32Double; */
}

/* save data associated with a point on a curve.
Enter with name of file, a curve and a valid point on that curve.
Returns 0 on success, -1 on failure.
*/

int save_curve (name, curv, point)
char *name;
CURVE *curv;
POINT *point;
{
FILE *save;
int err1, err2;

save = fopen(name, "w");
if ( !save) return(-1);
err1 = fwrite(curv, sizeof(CURVE), 1, save);
err2 = fwrite(point, sizeof(POINT), 1, save);
if (!(err1 && err2)) return(-1);
fclose(save);
return(0);
}

/* get data saved to disk.
Enter with name of file.
Returns with curve and point on that curve restored, 0 function value
or null results and -1 function value.
*/

int get_curve (name, curv, point)
char *name;
CURVE *curv;
POINT *point;
{
FILE *getcrv;
int err1, err2;

getcrv = fopen (name, "r");
if (!getcrv) return(-1);
err1 = fread(curv, sizeof(CURVE), 1, getcrv);
err2 = fread(point, sizeof(POINT), 1, getcrv);
fclose(getcrv);
if (!(err1 && err2)) return(-1);
return(0);
}

/* Random number initialization requires some arbitrary input. Request
32 bits from coin tossing. Feed to Mother of all random number
generators. Supposedly this generator has field size ~2^250. That's
roughly the size of the universe measured in cubic angstroms, so
this should be as close to "random" as deterministic can get.
*/

void init_rand()
{
FILE *rand;
INDEX i;
unsigned long mask;
char z1,cr;

if (! (rand = fopen("random.seed", "r"))) {
printf("\n pull out a coin.\n");
printf(" chose one side as '0'\n");
printf(" and the other side as '1'\n");
printf(" flip me some bits please\n");
random_seed = 0;
mask = 1;
i = 0;
while (i<32) {
printf("bit %d: ",i);
scanf("%c%c", &z1, &cr);
if (z1 == '1') {
random_seed |= mask;
i++;
mask <<= 1;
} else if (z1 == '0') {
i++;
mask <<= 1;
}
}
return;
}
fread (&random_seed, sizeof(long), 1, rand);
fclose(rand);
}

void close_rand()
{
FILE *rand;

if (rand = fopen("random.seed", "w")) {
fwrite(&random_seed, sizeof(long), 1, rand);
fclose(rand);
return;
}
printf("\n Catastrophic Failure: random.seed not saved\n");
}

/* print out a BIGINT with a label, to standard out. */

void big_print (strng, a)
char *strng;
BIGINT *a;
{
int i;

printf("%s",strng);
SUMLOOP(i) printf("%lx ",a->b[i]);
printf("\n");
}

/* Starting to get lazy, This needs to be part of a "point object" ultimately */

void print_point(title, p3)
char *title;
POINT *p3;
{
printf("\n%s\n",title);
big_print("x : ",&p3->x);
big_print("y : ",&p3->y);
big_print("z : ",&p3->z);
}

/* generate a random point on a random curve. Since these values are public anyway
no need to attempt security measures on random seed or resulting points */

void rand_curv_pnt( point, curve)
POINT *point;
CURVE *curve;
{
BIGINT f, y[2];
INDEX j;

/* generate a random regular curve */

curve->form = 0;
SUMLOOP(j) {
Mother(&random_seed);
curve->a6.b[j] = random_seed;
}
curve->a6.b[STRTPOS] &= UPRMASK;

/* generate a random point on that curve */

one (&point->z);
SUMLOOP(j) {
Mother(&random_seed);
point->x.b[j] = random_seed;
}
point->x.b[STRTPOS] &= UPRMASK;
fofx (&point->x, curve, &f);
while (gf_quadradic(&point->x, &f, &y[0]) > 0) {
point->x.b[LONGPOS] += 1L;
fofx(&point->x, curve, &f);
}
copy (&y[0], &point->y);
}

/* This hash function is for educational purposes. elliptic curves
have the property that there are some x's for which y^2 + x*y = f(x)
has no solution for y. Further, it takes 30 seconds to perform an
elliptic multiply for one block of data. A meg would be slow to hash.
*/

#define WORDS_NEEDED (LONGPOS-STRTPOS)

void eliptic_hash(num_words, data_ptr, result)
INDEX num_words;
ELEMENT *data_ptr;
BIGINT *result;
{
static init=0;
static CURVE hcurv;
static POINT hpnt;
BIGINT nxt_blok;
INDEX j, wrd_cnt;
POINT hashed, dashed;

/* initialize hash curve and point only once */

if (!init) {
if (get_curve( "hash.curve", &hcurv, &hpnt) < 0) {
printf("Error, can't open hash.curve\n");
exit(0);
}
init = -1;
}

/* initialize hash output value */

SUMLOOP(j) {
hashed.x.b[j] = hpnt.x.b[j];
hashed.y.b[j] = hpnt.y.b[j];
hashed.z.b[j] = hpnt.z.b[j];
}

/* grab a block of data that completely fills long words. Zero fill for
last unused block < max length.
*/
wrd_cnt = num_words;
null(&nxt_blok);
while (wrd_cnt) {
if (wrd_cnt >= WORDS_NEEDED) {
for (j=0; j < WORDS_NEEDED; j++)
nxt_blok.b[STRTPOS + j] = *data_ptr++;
wrd_cnt -= WORDS_NEEDED;
} else {
null(&nxt_blok);
while (wrd_cnt) nxt_blok.b[STRTPOS + wrd_cnt--] = *data_ptr++;
}

/* use block of data as multiplier to find next point on curve. */

printf(".");
elptic_mul(&nxt_blok, &hashed, &dashed, &hcurv);
copy_point(&dashed, &hashed);
}
copy (&hashed.x, result);
printf("\n");
}

/* smash bits around to create a key. experimental and for fun ok?!
Take last 4 bits of each pair of input characters to create one byte
of data block. Hash data block using LONGPOS-STRTPOS ELEMENTS as
multipliers of a single point, until whole data block consumed. More
than one or 2 factors is probably stupid (unless they are relatively
prime). And it would take too long. The 256 character input restriction
is much larger than most people use anyway.
*/

void elptic_key_gen( string, key)
char *string;
BIGINT *key;
{
char bit_string[128], *bs_ptr;
char byte0, byte1;
int byt_cnt;
INDEX num_elements;
INDEX i;

byt_cnt = 0;
bs_ptr = bit_string;
for (i=0; i<128; i++) bit_string[i] = 0;
while (*string) {
byte0 = (*string & 0xf) << 4;
string++;
byte1 = *string & 0xf;
*bs_ptr++ = byte0 | byte1;
byt_cnt++;
if (! *string) break;
else string++;
}
num_elements = byt_cnt/(WORDSIZE/8);
if (! num_elements) {
printf("key size too small\n");
return;
}
eliptic_hash( num_elements, bit_string, key);
}

/* gnu complains about gets, build my own. replace with something better, please! */

int get_string(buf, max)
char *buf;
int max;
{
int limit;
char *pointer;
char ch;

pointer = buf;
limit = 0;
fpurge(stdin);
while ((ch = getchar()) != '\n') {
*pointer = ch;
pointer++;
limit++;
if (limit > max) return(max);
}
return(limit);
}

/* generate a public key. If full = 0, only generates secret key.
for full = 1, fills entire public key with new random value.
*/

void public_key_gen( skey, pkey, full)
BIGINT *skey;
PUBKEY *pkey;
INDEX full;
{
char pass[MAX_PHRASE_SIZE];
char bit_string[MAX_PHRASE_SIZE/2];
char byte0, byte1;
INDEX byt_cnt, chr_cnt;

/* NOTE: this is not done correctly. turning off echo is platform dependent.
see routines in PGP (getstring(char *strbuf, unsigned maxlen, int echo) in
random.c) for much better ways to do this.
*/

printf("Enter pass phrase:\n");
get_string(pass, MAX_PHRASE_SIZE);
printf("\nGenerating secret key.\n");

byt_cnt = 0;
chr_cnt = 0;
while (pass[chr_cnt]) {
byte0 = (pass[chr_cnt++] & 0xF) << 4;
byte1 = pass[chr_cnt] & 0xF;
bit_string[byt_cnt++] = byte0 | byte1;
if (! pass[chr_cnt]) break;
else chr_cnt++;
}
eliptic_hash(byt_cnt/(WORDSIZE/8), bit_string, skey);
if (!full) return;

/* create random point and curve. for large enough fields this is not too
dangerous, but cardinality of curve and order of point really ought to
be checked.
*/

printf("\nGenerating public key.\n");
rand_curv_pnt(&pkey->p, &pkey->crv);
elptic_mul(skey, &pkey->p, &pkey->q, &pkey->crv);
flaten(&pkey->q);
printf("\nOK, now what name and address for this key?\n");
printf("Name: ");
get_string(&pkey->name, MAX_NAME_SIZE);
printf("Address: ");
get_string(&pkey->address, MAX_NAME_SIZE);
}

/* Save a public key to dsik file in ascii format. File name taken from field
of public key, up to first blank or tab. .PUB added as extension.

Returns 0 if ok, -1 on failure.
*/

static const char extensn[] = ".PUB";

int save_pub_key (PUBKEY *pub)
{
FILE *save;
char *cpy,*src;
BIGINT px, qx, ax, qbit, qxinv;
char filename[MAX_NAME_SIZE+5];
INDEX i,j;

/* create key name file */

src = pub->name;
while (*src == ' ' || *src == '\t') src++;
cpy = filename;
while (*src != ' ' && *src != '\t') *cpy++ = *src++;
*cpy = '\0';
strcat (filename, extensn);
if (! (save = fopen(filename, "w"))) {
printf("can't create %s\n",filename);
return(-1);
}

/* use last bit of y to define all of it. Store in msb of first ELEMENT used.
So far as I can tell, this is valid for type 1 normal basis (i.e.
there are no 2^m+1 for m congruent to 5 valid field primes.)
Point p is always y[0], so no need to encode it. For q, compute y/x
to determine which y to use from quadradic solution. See Menezes, pg 92.
*/

copy(&pub->p.x, &px);
copy(&pub->q.x, &qx);
copy(&pub->crv.a6, &ax);
opt_inv(&pub->q.x, &qxinv);
opt_mul(&pub->q.y, &qxinv, &qbit);
if (1 & qbit.b[LONGPOS]) qx.b[STRTPOS] |= SUBMASK;

/* may want to add the following some time if a2 ever used, can be attached after
a6 and full curve takes minimal storage:
if (pub->crv.form) ax.b[STRTPOS] |= SUBMASK;
*/

fprintf(save, "%s\n", pub->name);
fprintf(save, "%s\n", pub->address);
SUMLOOP(i) fprintf(save, "%lx ", px.b[i]);
fprintf(save, "\n");
SUMLOOP(i) fprintf(save, "%lx ", qx.b[i]);
fprintf(save, "\n");
SUMLOOP(i) fprintf(save, "%lx ", ax.b[i]);
fprintf(save, "\n");
/* output a2 here */
fclose(save);
}

/* Recover a public key from disk file. Assume ascii format of save_pub_key.
Enter with file name (with or without extension) and pointer to a
storage block. Returns 0 on success, -1 on failure.
*/

int restore_pub_key( char *name, PUBKEY *pub)
{
FILE *restore;
char filename[MAX_NAME_SIZE+5];
INDEX i,j;
BIGINT px, qx, ax, y[2], f;

/* check for extension on file name and open file */

if ( !( j = (INDEX)strlen(name))) {
printf("filename too long: %s\n",name);
return(-1);
}
strcpy(filename,name);
if (strcmp(&name[j-4], extensn) && j<=MAX_NAME_SIZE)
strcat(filename,extensn);
if ( !(restore = fopen(filename, "r"))) {
printf("can't open file %s\n");
return(-1);
}

/* read in raw data */

null( &px);
null( &qx);
null( &ax);
fgets(pub->name, (size_t) MAX_NAME_SIZE, restore);
pub->name[strlen( pub->name) - 1] = '\0';
fgets(pub->address, (size_t)MAX_NAME_SIZE, restore);
pub->address[strlen( pub->address) - 1] = '\0';
SUMLOOP(i) fscanf(restore, "%lx", &px.b[i]);
SUMLOOP(i) fscanf(restore, "%lx", &qx.b[i]);
SUMLOOP(i) fscanf(restore, "%lx", &ax.b[i]);
/* read in a2 here */
fclose(restore);

/* create curve parameters. fix this if form == 1 ever used. */

null(&pub->crv.a2);
pub->crv.form = 0;
copy(&ax, &pub->crv.a6);

copy( &px, &pub->p.x);
fofx( &px, &pub->crv, &f);
if (gf_quadradic( &px, &f, &y[0])) {
printf("Key in file %s does not have valid point on given curve.\n",
name);
printf("This is a major malfunction.\n");
return(-1);
}
copy (&y[0], &pub->p.y);
one( &pub->p.z);

/* get last bit of y/x for subscript into quadradic results */

if (qx.b[STRTPOS] & SUBMASK) {
j = 1;
qx.b[STRTPOS] &= UPRMASK;
} else
j = 0;
copy( &qx, &pub->q.x);
fofx( &qx, &pub->crv, &f);
if (gf_quadradic( &qx, &f, &y[0])) {
printf("Key in file %s does not have valid point on given curve.\n",
name);
printf("This is a major malfunction.\n");
return(-1);
}
copy (&y[j], &pub->q.y);
one( &pub->q.z);
return(0);
}

void print_pubkey(PUBKEY *pk)
{

printf("name: %s\n",pk->name);
printf("address: %s\n",pk->address);
printf("public key is:\n");
big_print("curve: ",&pk->crv.a6);
print_point(" P:",&pk->p);
print_point(" Q:",&pk->q);
}
/*main()
{
char file[256];
BIGINT secret_key;
PUBKEY public_key, recovered_key;

init_opt_math();
init_rand();

public_key_gen(&secret_key, &public_key, 1);
big_print("secret key: ",&secret_key);
print_pubkey(&public_key);
save_pub_key(&public_key);
printf("input file name for previous key: ");
scanf("%s",&file);
restore_pub_key(file, &recovered_key);
print_pubkey(&recovered_key);
close_rand();
}*/
/****** krypto_knot.c *****/
/********************************************************************************
* *
* The purpose of this file is to tie together all the subroutines from *
* the elliptic curve optimal normal basis suite to create a key hiding system. *
* The actual compression and encoding should be performed by standard *
* algorithms such as arith-n (compression book) and blowfish (Dr. Dobbs's *
* Journal or Applied Cryptography. The complete system would then violate ITAR*
* and not be accessable, so you'll have to hack that yourself. *
* *
********************************************************************************/

#include <stdio.h>
#include "bigint.h"
#include "eliptic.h"
#include "eliptic_keys.h"

extern void null(BIGINT*);
extern void copy(BIGINT*, BIGINT*);
extern void fofx(BIGINT*, CURVE*, BIGINT*);
extern int gf_quadradic(BIGINT*, BIGINT*, BIGINT*);
extern void one(BIGINT*);
extern void Mother(unsigned long*);
extern void esum(POINT*, POINT*, POINT*, CURVE*);
extern void esub(POINT*, POINT*, POINT*, CURVE*);
extern void elptic_mul(BIGINT*, POINT*, POINT*, CURVE*);
extern void flaten(POINT*);
extern void public_key_gen(BIGINT*, PUBKEY*, INDEX);
extern void restore_pub_key( char*, PUBKEY*);
extern void print_pubkey( PUBKEY*);
extern void big_print(char*, BIGINT*);

extern unsigned long random_seed;

/* encrypt a session key. Enter with given session key to hide, public key
to hide it in, and storage block for result. It is a waste of space to use a
PUBKEY for this, too bad.

session == pointer to key to be hidden
pk == pointer to public key block to use
ek == pointer to resultant key block. ek->p holds kP, ek->q holds S+kQ
*/

void elptic_encrypt(BIGINT *session, PUBKEY *pk, PUBKEY *ek)
{
INDEX i;
BIGINT k, f, y[2];
POINT s, t;

/* encode session key onto a random point using this public key. */

null(&k);
Mother(&random_seed);
copy(session, &k);
k.b[STRTPOS] = random_seed & UPRMASK;

/* note that this assumes session key < NUMBITS and that STRTPOS ELEMENT is free
to be clobbered. For all reasonable encoding schemes this shouldn't be a problem.
*/

fofx( &k, &pk->crv, &f);
while (gf_quadradic(&k, &f, y)) {
k.b[STRTPOS]++;
fofx(&k, &pk->crv, &f);
}
copy( &k, &s.x);
copy( &y[1],&s.y); /* use 1 just to be different, why not eh? */
one(&s.z);

/* next generate a random multiplier k */

null(&k);
SUMLOOP(i) {
Mother(&random_seed);
k.b[i] = random_seed;
}
k.b[STRTPOS] &= UPRMASK;

/* do 2 multiplies, kp and kq */

elptic_mul(&k, &pk->p, &ek->p, &pk->crv);
flaten( &ek->p);
elptic_mul(&k, &pk->q, &t, &pk->crv);

/* add s to kQ as final step */

esum(&s, &t, &ek->q, &pk->crv);
flaten(&ek->q);
ek->crv.form = pk->crv.form;
copy( &pk->crv.a2, &ek->crv.a2);
copy( &pk->crv.a6, &ek->crv.a6);
}

/* decrypt session key from public and encrypted key.
returns 0 if successful, -1 on failure (wrong pass phrase).
*/

int elptic_decrypt(BIGINT *session, PUBKEY *pk, PUBKEY *ek)
{
INDEX i;
BIGINT skey;
POINT check, t, s;

/* first ensure you can generate secret key. */

public_key_gen(&skey, pk, 0);
elptic_mul(&skey, &pk->p, &check, &pk->crv);
flaten(&check);
SUMLOOP(i) {
if (check.x.b[i] != pk->q.x.b[i]) {
printf("Invalid pass phrase.\n");
return(-1);
}
}

/* next compute T = aR and subtract from R' to get S */

elptic_mul(&skey, &ek->p, &t, &pk->crv);
esub(&ek->q, &t, &s, &pk->crv);
flaten(&s);

/* clear out encoding garbage and return session key */

copy( &s.x, session);
session->b[STRTPOS] = 0;
return(0);
}

main()
{
char file[256];
BIGINT session_key, recovered_key, secret_key;
PUBKEY public_key, hidden_key;
INDEX i;

init_opt_math();
init_rand();

/* for this test, assume you have already generated a public key (and remember
the pass phrase!). Read in key file from disk. */

/* printf("input file name for previous key: ");
scanf("%s",&file);
restore_pub_key(file, &public_key);
*/
public_key_gen(&secret_key, &public_key, 1);
print_pubkey(&public_key);
big_print("secret key: ", &secret_key);

/* generate a session key... */

printf("Generating session key and encryping it...\n");
SUMLOOP(i) {
Mother(&random_seed);
session_key.b[i] = random_seed;
}
elptic_encrypt(&session_key, &public_key, &hidden_key);
print_pubkey(&hidden_key);
big_print("session_key: ",&session_key);
elptic_decrypt(&recovered_key, &public_key, &hidden_key);
big_print("recovered key: ",&recovered_key);

close_rand();
}

# simple makefile for elliptic curve stuff

test: eliptic.o bigint.o support.o krypto_knot.o
ld -o eliptic /lib/crt0.o krypto_knot.o support.o eliptic.o bigint.o -lc

krypto_knot.o: eliptic.h bigint.h eliptic_keys.h krypto_knot.o
cc -c -g krypto_knot.c

support.o: eliptic_keys.h eliptic.h bigint.h support.c
# cc -c -O support.c
cc -c -g support.c

eliptic.o: eliptic.h bigint.h eliptic.c
# cc -c -O eliptic.c
cc -c -g eliptic.c

bigint.o: bigint.h bigint.c
cc -c -O bigint.c

/***** optprime.dat *****/
The following primes are valid for type 1 optimal normal
basis math. They have the property that 2 is a generator
among other things.

2 3 11 13 29 53 59 83 107 149
173 179 227 269 293 317 347 389 467 509
557 563 587 653 773 797 1019 1109 1187 1229
1283 1307 1493 1523 1619 1637 1733 1907 1949 1997
2027 2099 2309 2459 2477 2579 2693 2819 2837 2909
2957 2963 3203 3413 3467 3533 3677 3779 3803 3947
3989 4133 4139 4157 4253 4259 4283 4349 4373 4493
4517 4547 4787 5099 5189 5309 5387 5483 5507 5693
5717 5813 5939 6173 6197 6269 6317 6389 6653 6659
6779 6827 6899 7013 7109 7187 7517 7523 7643 7949
8069 8117 8147 8573 8699 8747 8819 8963 9173 9467
9533 9587 9749 10163 10589 10667 10709 10733 10853 10883
11003 11069 11213 11483 11549 11699 11813 12107 12149 12197
12203 12227 12269 12347 12437 12539 12653 12659 12899 12917
13037 13043 13163 13229 13523 13829 13877 13997 14243 14387
14549 14699 14867 14957 15077 15083 15173 15299 15413 15629
15683 15773 15803 16139 16187 16229 16547 17027 17093 17189
17387 17483 17789 17939 18059 18077 18269 18413 18443 18587
18917 18947 19037 19157 19259 19379 19949 19973 19997 20123
20477 20507 20627 20717 20789 21059 21179 21227 21419 21467
21563 21773 22013 22109 22229 22277 22613 22637 22643 22739
22787 22973 23099 23117 23357 23603 23627 23813 23819 24029
24083 24203 24317 24533 24659 24917 24989 25307 25349 25373
25469 25589 25643 26003 26099 26189 26309 26459 26627 26693
26717 26813 27107 27299 27803 27827 28019 28109 28163 28229
28277 28307 28499 28517 28643 28949 28979 29123 29243 29333
29339 29483 29573 29669 29837 30029 30197 30203 30293 30323
30347 30467 30539 30557 30677 30803 30869 30893 31013 31139
31259 31469 31517 31547 31973 32003 32069 32213 32237 32507
32603 32717 32843 32933 32987 33053 33107 33149 33317 33347
33413 33773 34157 34253 34589 34667 34757 34877 34949 35117
35339 35363 35573 35963 36083 36269 36299 36467 36629 36683
36749 36923 37277 37397 37547 37589
Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    0 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    0 Files
  • 23
    Apr 23rd
    0 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close