mpextendedgcd.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include "os.h"
  2. #include <mp.h>
  3. #define iseven(a) (((a)->p[0] & 1) == 0)
  4. // extended binary gcd
  5. //
  6. // For a anv b it solves, v = gcd(a,b) and finds x and y s.t.
  7. // ax + by = v
  8. //
  9. // Handbook of Applied Cryptography, Menezes et al, 1997, pg 608.
  10. void
  11. mpextendedgcd(mpint *a, mpint *b, mpint *v, mpint *x, mpint *y)
  12. {
  13. mpint *u, *A, *B, *C, *D;
  14. int g;
  15. if(a->sign < 0 || b->sign < 0){
  16. mpassign(mpzero, v);
  17. mpassign(mpzero, y);
  18. mpassign(mpzero, x);
  19. return;
  20. }
  21. if(a->top == 0){
  22. mpassign(b, v);
  23. mpassign(mpone, y);
  24. mpassign(mpzero, x);
  25. return;
  26. }
  27. if(b->top == 0){
  28. mpassign(a, v);
  29. mpassign(mpone, x);
  30. mpassign(mpzero, y);
  31. return;
  32. }
  33. g = 0;
  34. a = mpcopy(a);
  35. b = mpcopy(b);
  36. while(iseven(a) && iseven(b)){
  37. mpright(a, 1, a);
  38. mpright(b, 1, b);
  39. g++;
  40. }
  41. u = mpcopy(a);
  42. mpassign(b, v);
  43. A = mpcopy(mpone);
  44. B = mpcopy(mpzero);
  45. C = mpcopy(mpzero);
  46. D = mpcopy(mpone);
  47. for(;;) {
  48. // print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
  49. while(iseven(u)){
  50. mpright(u, 1, u);
  51. if(!iseven(A) || !iseven(B)) {
  52. mpadd(A, b, A);
  53. mpsub(B, a, B);
  54. }
  55. mpright(A, 1, A);
  56. mpright(B, 1, B);
  57. }
  58. // print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
  59. while(iseven(v)){
  60. mpright(v, 1, v);
  61. if(!iseven(C) || !iseven(D)) {
  62. mpadd(C, b, C);
  63. mpsub(D, a, D);
  64. }
  65. mpright(C, 1, C);
  66. mpright(D, 1, D);
  67. }
  68. // print("%B %B %B %B %B %B\n", u, v, A, B, C, D);
  69. if(mpcmp(u, v) >= 0){
  70. mpsub(u, v, u);
  71. mpsub(A, C, A);
  72. mpsub(B, D, B);
  73. } else {
  74. mpsub(v, u, v);
  75. mpsub(C, A, C);
  76. mpsub(D, B, D);
  77. }
  78. if(u->top == 0)
  79. break;
  80. }
  81. mpassign(C, x);
  82. mpassign(D, y);
  83. mpleft(v, g, v);
  84. mpfree(A);
  85. mpfree(B);
  86. mpfree(C);
  87. mpfree(D);
  88. mpfree(u);
  89. mpfree(a);
  90. mpfree(b);
  91. return;
  92. }