#include "os.h" | |
#include <mp.h> | |
#define iseven(a) (((a)->p[0] & 1) == 0) | |
// extended binary gcd | |
// | |
// For a anv b it solves, v = gcd(a,b) and finds x and y s.t. | |
// ax + by = v | |
// | |
// Handbook of Applied Cryptography, Menezes et al, 1997, pg 608. | |
void | |
mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y) | |
{ | |
mpint *u, *A, *B, *C, *D; | |
int g; | |
if(a->sign < 0 || b->sign < 0){ | |
mpassign(mpzero, v); | |
mpassign(mpzero, y); | |
mpassign(mpzero, x); | |
return; | |
} | |
if(a->top == 0){ | |
mpassign(b, v); | |
mpassign(mpone, y); | |
mpassign(mpzero, x); | |
return; | |
} | |
if(b->top == 0){ | |
mpassign(a, v); | |
mpassign(mpone, x); | |
mpassign(mpzero, y); | |
return; | |
} | |
g = 0; | |
a = mpcopy(a); | |
b = mpcopy(b); | |
while(iseven(a) && iseven(b)){ | |
mpright(a, 1, a); | |
mpright(b, 1, b); | |
g++; | |
} | |
u = mpcopy(a); | |
mpassign(b, v); | |
A = mpcopy(mpone); | |
B = mpcopy(mpzero); | |
C = mpcopy(mpzero); | |
D = mpcopy(mpone); | |
for(;;) { | |
// print("%B %B %B %B %B %B\n", u, v, A, B, C, D); | |
while(iseven(u)){ | |
mpright(u, 1, u); | |
if(!iseven(A) || !iseven(B)) { | |
mpadd(A, b, A); | |
mpsub(B, a, B); | |
} | |
mpright(A, 1, A); | |
mpright(B, 1, B); | |
} | |
// print("%B %B %B %B %B %B\n", u, v, A, B, C, D); | |
while(iseven(v)){ | |
mpright(v, 1, v); | |
if(!iseven(C) || !iseven(D)) { | |
mpadd(C, b, C); | |
mpsub(D, a, D); | |
} | |
mpright(C, 1, C); | |
mpright(D, 1, D); | |
} | |
// print("%B %B %B %B %B %B\n", u, v, A, B, C, D); | |
if(mpcmp(u, v) >= 0){ | |
mpsub(u, v, u); | |
mpsub(A, C, A); | |
mpsub(B, D, B); | |
} else { | |
mpsub(v, u, v); | |
mpsub(C, A, C); | |
mpsub(D, B, D); | |
} | |
if(u->top == 0) | |
break; | |
} | |
mpassign(C, x); | |
mpassign(D, y); | |
mpleft(v, g, v); | |
mpfree(A); | |
mpfree(B); | |
mpfree(C); | |
mpfree(D); | |
mpfree(u); | |
mpfree(a); | |
mpfree(b); | |
return; | |
} |