#include "os.h" | |
#include <mp.h> | |
// extended euclid | |
// | |
// For a and b it solves, d = gcd(a,b) and finds x and y s.t. | |
// ax + by = d | |
// | |
// Handbook of Applied Cryptography, Menezes et al, 1997, pg 67 | |
void | |
mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y) | |
{ | |
mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r; | |
if(a->sign<0 || b->sign<0) | |
sysfatal("mpeuclid: negative arg"); | |
if(mpcmp(a, b) < 0){ | |
tmp = a; | |
a = b; | |
b = tmp; | |
tmp = x; | |
x = y; | |
y = tmp; | |
} | |
if(b->top == 0){ | |
mpassign(a, d); | |
mpassign(mpone, x); | |
mpassign(mpzero, y); | |
return; | |
} | |
a = mpcopy(a); | |
b = mpcopy(b); | |
x0 = mpnew(0); | |
x1 = mpcopy(mpzero); | |
x2 = mpcopy(mpone); | |
y0 = mpnew(0); | |
y1 = mpcopy(mpone); | |
y2 = mpcopy(mpzero); | |
q = mpnew(0); | |
r = mpnew(0); | |
while(b->top != 0 && b->sign > 0){ | |
// q = a/b | |
// r = a mod b | |
mpdiv(a, b, q, r); | |
// x0 = x2 - qx1 | |
mpmul(q, x1, x0); | |
mpsub(x2, x0, x0); | |
// y0 = y2 - qy1 | |
mpmul(q, y1, y0); | |
mpsub(y2, y0, y0); | |
// rotate values | |
tmp = a; | |
a = b; | |
b = r; | |
r = tmp; | |
tmp = x2; | |
x2 = x1; | |
x1 = x0; | |
x0 = tmp; | |
tmp = y2; | |
y2 = y1; | |
y1 = y0; | |
y0 = tmp; | |
} | |
mpassign(a, d); | |
mpassign(x2, x); | |
mpassign(y2, y); | |
mpfree(x0); | |
mpfree(x1); | |
mpfree(x2); | |
mpfree(y0); | |
mpfree(y1); | |
mpfree(y2); | |
mpfree(q); | |
mpfree(r); | |
mpfree(a); | |
mpfree(b); | |
} |