| #include "os.h" |
| #include <mp.h> |
| |
| // chinese remainder theorem |
| // |
| // handbook of applied cryptography, menezes et al, 1997, pp 610 - 613 |
| |
| struct CRTpre |
| { |
| int n; // number of moduli |
| mpint **m; // pointer to moduli |
| mpint **c; // precomputed coefficients |
| mpint **p; // precomputed products |
| mpint *a[1]; // local storage |
| }; |
| |
| // setup crt info, returns a newly created structure |
| CRTpre* |
| crtpre(int n, mpint **m) |
| { |
| CRTpre *crt; |
| int i, j; |
| mpint *u; |
| |
| crt = malloc(sizeof(CRTpre)+sizeof(mpint)*3*n); |
| if(crt == nil) |
| sysfatal("crtpre: %r"); |
| crt->m = crt->a; |
| crt->c = crt->a+n; |
| crt->p = crt->c+n; |
| crt->n = n; |
| |
| // make a copy of the moduli |
| for(i = 0; i < n; i++) |
| crt->m[i] = mpcopy(m[i]); |
| |
| // precompute the products |
| u = mpcopy(mpone); |
| for(i = 0; i < n; i++){ |
| mpmul(u, m[i], u); |
| crt->p[i] = mpcopy(u); |
| } |
| |
| // precompute the coefficients |
| for(i = 1; i < n; i++){ |
| crt->c[i] = mpcopy(mpone); |
| for(j = 0; j < i; j++){ |
| mpinvert(m[j], m[i], u); |
| mpmul(u, crt->c[i], u); |
| mpmod(u, m[i], crt->c[i]); |
| } |
| } |
| |
| mpfree(u); |
| |
| return crt; |
| } |
| |
| void |
| crtprefree(CRTpre *crt) |
| { |
| int i; |
| |
| for(i = 0; i < crt->n; i++){ |
| if(i != 0) |
| mpfree(crt->c[i]); |
| mpfree(crt->p[i]); |
| mpfree(crt->m[i]); |
| } |
| free(crt); |
| } |
| |
| // convert to residues, returns a newly created structure |
| CRTres* |
| crtin(CRTpre *crt, mpint *x) |
| { |
| int i; |
| CRTres *res; |
| |
| res = malloc(sizeof(CRTres)+sizeof(mpint)*crt->n); |
| if(res == nil) |
| sysfatal("crtin: %r"); |
| res->n = crt->n; |
| for(i = 0; i < res->n; i++){ |
| res->r[i] = mpnew(0); |
| mpmod(x, crt->m[i], res->r[i]); |
| } |
| return res; |
| } |
| |
| // garners algorithm for converting residue form to linear |
| void |
| crtout(CRTpre *crt, CRTres *res, mpint *x) |
| { |
| mpint *u; |
| int i; |
| |
| u = mpnew(0); |
| mpassign(res->r[0], x); |
| |
| for(i = 1; i < crt->n; i++){ |
| mpsub(res->r[i], x, u); |
| mpmul(u, crt->c[i], u); |
| mpmod(u, crt->m[i], u); |
| mpmul(u, crt->p[i-1], u); |
| mpadd(x, u, x); |
| } |
| |
| mpfree(u); |
| } |
| |
| // free the residue |
| void |
| crtresfree(CRTres *res) |
| { |
| int i; |
| |
| for(i = 0; i < res->n; i++) |
| mpfree(res->r[i]); |
| free(res); |
| } |