crt.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include "os.h"
  2. #include <mp.h>
  3. #include <libsec.h>
  4. // chinese remainder theorem
  5. //
  6. // handbook of applied cryptography, menezes et al, 1997, pp 610 - 613
  7. struct CRTpre
  8. {
  9. int n; // number of moduli
  10. mpint **m; // pointer to moduli
  11. mpint **c; // precomputed coefficients
  12. mpint **p; // precomputed products
  13. mpint *a[1]; // local storage
  14. };
  15. // setup crt info, returns a newly created structure
  16. CRTpre*
  17. crtpre(int n, mpint **m)
  18. {
  19. CRTpre *crt;
  20. int i, j;
  21. mpint *u;
  22. crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n);
  23. if(crt == nil)
  24. sysfatal("crtpre: %r");
  25. crt->m = crt->a;
  26. crt->c = crt->a+n;
  27. crt->p = crt->c+n;
  28. crt->n = n;
  29. // make a copy of the moduli
  30. for(i = 0; i < n; i++)
  31. crt->m[i] = mpcopy(m[i]);
  32. // precompute the products
  33. u = mpcopy(mpone);
  34. for(i = 0; i < n; i++){
  35. mpmul(u, m[i], u);
  36. crt->p[i] = mpcopy(u);
  37. }
  38. // precompute the coefficients
  39. for(i = 1; i < n; i++){
  40. crt->c[i] = mpcopy(mpone);
  41. for(j = 0; j < i; j++){
  42. mpinvert(m[j], m[i], u);
  43. mpmul(u, crt->c[i], u);
  44. mpmod(u, m[i], crt->c[i]);
  45. }
  46. }
  47. mpfree(u);
  48. return crt;
  49. }
  50. void
  51. crtprefree(CRTpre *crt)
  52. {
  53. int i;
  54. for(i = 0; i < crt->n; i++){
  55. if(i != 0)
  56. mpfree(crt->c[i]);
  57. mpfree(crt->p[i]);
  58. mpfree(crt->m[i]);
  59. }
  60. free(crt);
  61. }
  62. // convert to residues, returns a newly created structure
  63. CRTres*
  64. crtin(CRTpre *crt, mpint *x)
  65. {
  66. int i;
  67. CRTres *res;
  68. res = malloc(sizeof(CRTres)+sizeof(mpint)*crt->n);
  69. if(res == nil)
  70. sysfatal("crtin: %r");
  71. res->n = crt->n;
  72. for(i = 0; i < res->n; i++){
  73. res->r[i] = mpnew(0);
  74. mpmod(x, crt->m[i], res->r[i]);
  75. }
  76. return res;
  77. }
  78. // garners algorithm for converting residue form to linear
  79. void
  80. crtout(CRTpre *crt, CRTres *res, mpint *x)
  81. {
  82. mpint *u;
  83. int i;
  84. u = mpnew(0);
  85. mpassign(res->r[0], x);
  86. for(i = 1; i < crt->n; i++){
  87. mpsub(res->r[i], x, u);
  88. mpmul(u, crt->c[i], u);
  89. mpmod(u, crt->m[i], u);
  90. mpmul(u, crt->p[i-1], u);
  91. mpadd(x, u, x);
  92. }
  93. mpfree(u);
  94. }
  95. // free the residue
  96. void
  97. crtresfree(CRTres *res)
  98. {
  99. int i;
  100. for(i = 0; i < res->n; i++)
  101. mpfree(res->r[i]);
  102. free(res);
  103. }