mpeuclid.c 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include "os.h"
  2. #include <mp.h>
  3. // extended euclid
  4. //
  5. // For a and b it solves, d = gcd(a,b) and finds x and y s.t.
  6. // ax + by = d
  7. //
  8. // Handbook of Applied Cryptography, Menezes et al, 1997, pg 67
  9. void
  10. mpeuclid(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y)
  11. {
  12. mpint *tmp, *x0, *x1, *x2, *y0, *y1, *y2, *q, *r;
  13. if(a->sign<0 || b->sign<0)
  14. sysfatal("mpeuclid: negative arg");
  15. if(mpcmp(a, b) < 0){
  16. tmp = a;
  17. a = b;
  18. b = tmp;
  19. tmp = x;
  20. x = y;
  21. y = tmp;
  22. }
  23. if(b->top == 0){
  24. mpassign(a, d);
  25. mpassign(mpone, x);
  26. mpassign(mpzero, y);
  27. return;
  28. }
  29. a = mpcopy(a);
  30. b = mpcopy(b);
  31. x0 = mpnew(0);
  32. x1 = mpcopy(mpzero);
  33. x2 = mpcopy(mpone);
  34. y0 = mpnew(0);
  35. y1 = mpcopy(mpone);
  36. y2 = mpcopy(mpzero);
  37. q = mpnew(0);
  38. r = mpnew(0);
  39. while(b->top != 0 && b->sign > 0){
  40. // q = a/b
  41. // r = a mod b
  42. mpdiv(a, b, q, r);
  43. // x0 = x2 - qx1
  44. mpmul(q, x1, x0);
  45. mpsub(x2, x0, x0);
  46. // y0 = y2 - qy1
  47. mpmul(q, y1, y0);
  48. mpsub(y2, y0, y0);
  49. // rotate values
  50. tmp = a;
  51. a = b;
  52. b = r;
  53. r = tmp;
  54. tmp = x2;
  55. x2 = x1;
  56. x1 = x0;
  57. x0 = tmp;
  58. tmp = y2;
  59. y2 = y1;
  60. y1 = y0;
  61. y0 = tmp;
  62. }
  63. mpassign(a, d);
  64. mpassign(x2, x);
  65. mpassign(y2, y);
  66. mpfree(x0);
  67. mpfree(x1);
  68. mpfree(x2);
  69. mpfree(y0);
  70. mpfree(y1);
  71. mpfree(y2);
  72. mpfree(q);
  73. mpfree(r);
  74. mpfree(a);
  75. mpfree(b);
  76. }