⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpi.c

📁 支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS #11, PKCS #12, S/MIME, X.509v3证书等安全协议或标准的开发库编译用到NSPR
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* Terminate the loop, if the quotient is zero */    if(mp_cmp_z(&t) == MP_EQ)      break;    /* x = x - t       */    if((res = mp_sub(&x, &t, &x)) != MP_OKAY)      goto CLEANUP;  }  /* Copy result to output parameter */  mp_sub_d(&x, 1, &x);  s_mp_exch(&x, b); CLEANUP:  mp_clear(&x); X:  mp_clear(&t);   return res;} /* end mp_sqrt() *//* }}} *//* }}} *//*------------------------------------------------------------------------*//* {{{ Modular arithmetic */#if MP_MODARITH/* {{{ mp_addmod(a, b, m, c) *//*  mp_addmod(a, b, m, c)  Compute c = (a + b) mod m */mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_add(a, b, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;}/* }}} *//* {{{ mp_submod(a, b, m, c) *//*  mp_submod(a, b, m, c)  Compute c = (a - b) mod m */mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_sub(a, b, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;}/* }}} *//* {{{ mp_mulmod(a, b, m, c) *//*  mp_mulmod(a, b, m, c)  Compute c = (a * b) mod m */mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_mul(a, b, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;}/* }}} *//* {{{ mp_sqrmod(a, m, c) */#if MP_SQUAREmp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_sqr(a, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;} /* end mp_sqrmod() */#endif/* }}} *//* {{{ s_mp_exptmod(a, b, m, c) *//*  s_mp_exptmod(a, b, m, c)  Compute c = (a ** b) mod m.  Uses a standard square-and-multiply  method with modular reductions at each step. (This is basically the  same code as mp_expt(), except for the addition of the reductions)    The modular reductions are done using Barrett's algorithm (see  s_mp_reduce() below for details) */mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c){  mp_int   s, x, mu;  mp_err   res;  mp_digit d;  int      dig, bit;  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);  if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)    return MP_RANGE;  if((res = mp_init(&s)) != MP_OKAY)    return res;  if((res = mp_init_copy(&x, a)) != MP_OKAY ||     (res = mp_mod(&x, m, &x)) != MP_OKAY)    goto X;  if((res = mp_init(&mu)) != MP_OKAY)    goto MU;  mp_set(&s, 1);  /* mu = b^2k / m */  s_mp_add_d(&mu, 1);   s_mp_lshd(&mu, 2 * USED(m));  if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)    goto CLEANUP;  /* Loop over digits of b in ascending order, except highest order */  for(dig = 0; dig < (USED(b) - 1); dig++) {    d = DIGIT(b, dig);    /* Loop over the bits of the lower-order digits */    for(bit = 0; bit < DIGIT_BIT; bit++) {      if(d & 1) {	if((res = s_mp_mul(&s, &x)) != MP_OKAY)	  goto CLEANUP;	if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)	  goto CLEANUP;      }      d >>= 1;      if((res = s_mp_sqr(&x)) != MP_OKAY)	goto CLEANUP;      if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)	goto CLEANUP;    }  }  /* Now do the last digit... */  d = DIGIT(b, dig);  while(d) {    if(d & 1) {      if((res = s_mp_mul(&s, &x)) != MP_OKAY)	goto CLEANUP;      if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)	goto CLEANUP;    }    d >>= 1;    if((res = s_mp_sqr(&x)) != MP_OKAY)      goto CLEANUP;    if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)      goto CLEANUP;  }  s_mp_exch(&s, c); CLEANUP:  mp_clear(&mu); MU:  mp_clear(&x); X:  mp_clear(&s);  return res;} /* end s_mp_exptmod() *//* }}} *//* {{{ mp_exptmod_d(a, d, m, c) */mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c){  mp_int   s, x;  mp_err   res;  ARGCHK(a != NULL && c != NULL, MP_BADARG);  if((res = mp_init(&s)) != MP_OKAY)    return res;  if((res = mp_init_copy(&x, a)) != MP_OKAY)    goto X;  mp_set(&s, 1);  while(d != 0) {    if(d & 1) {      if((res = s_mp_mul(&s, &x)) != MP_OKAY ||	 (res = mp_mod(&s, m, &s)) != MP_OKAY)	goto CLEANUP;    }    d /= 2;    if((res = s_mp_sqr(&x)) != MP_OKAY ||       (res = mp_mod(&x, m, &x)) != MP_OKAY)      goto CLEANUP;  }  s_mp_exch(&s, c);CLEANUP:  mp_clear(&x);X:  mp_clear(&s);  return res;} /* end mp_exptmod_d() *//* }}} */#endif /* if MP_MODARITH *//* }}} *//*------------------------------------------------------------------------*//* {{{ Comparison functions *//* {{{ mp_cmp_z(a) *//*  mp_cmp_z(a)  Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0. */int    mp_cmp_z(const mp_int *a){  if(SIGN(a) == NEG)    return MP_LT;  else if(USED(a) == 1 && DIGIT(a, 0) == 0)    return MP_EQ;  else    return MP_GT;} /* end mp_cmp_z() *//* }}} *//* {{{ mp_cmp_d(a, d) *//*  mp_cmp_d(a, d)  Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d */int    mp_cmp_d(const mp_int *a, mp_digit d){  ARGCHK(a != NULL, MP_EQ);  if(SIGN(a) == NEG)    return MP_LT;  return s_mp_cmp_d(a, d);} /* end mp_cmp_d() *//* }}} *//* {{{ mp_cmp(a, b) */int    mp_cmp(const mp_int *a, const mp_int *b){  ARGCHK(a != NULL && b != NULL, MP_EQ);  if(SIGN(a) == SIGN(b)) {    int  mag;    if((mag = s_mp_cmp(a, b)) == MP_EQ)      return MP_EQ;    if(SIGN(a) == ZPOS)      return mag;    else      return -mag;  } else if(SIGN(a) == ZPOS) {    return MP_GT;  } else {    return MP_LT;  }} /* end mp_cmp() *//* }}} *//* {{{ mp_cmp_mag(a, b) *//*  mp_cmp_mag(a, b)  Compares |a| <=> |b|, and returns an appropriate comparison result */int    mp_cmp_mag(mp_int *a, mp_int *b){  ARGCHK(a != NULL && b != NULL, MP_EQ);  return s_mp_cmp(a, b);} /* end mp_cmp_mag() *//* }}} *//* {{{ mp_cmp_int(a, z) *//*  This just converts z to an mp_int, and uses the existing comparison  routines.  This is sort of inefficient, but it's not clear to me how  frequently this wil get used anyway.  For small positive constants,  you can always use mp_cmp_d(), and for zero, there is mp_cmp_z(). */int    mp_cmp_int(const mp_int *a, long z){  mp_int  tmp;  int     out;  ARGCHK(a != NULL, MP_EQ);    mp_init(&tmp); mp_set_int(&tmp, z);  out = mp_cmp(a, &tmp);  mp_clear(&tmp);  return out;} /* end mp_cmp_int() *//* }}} *//* {{{ mp_isodd(a) *//*  mp_isodd(a)  Returns a true (non-zero) value if a is odd, false (zero) otherwise. */int    mp_isodd(const mp_int *a){  ARGCHK(a != NULL, 0);  return (int)(DIGIT(a, 0) & 1);} /* end mp_isodd() *//* }}} *//* {{{ mp_iseven(a) */int    mp_iseven(const mp_int *a){  return !mp_isodd(a);} /* end mp_iseven() *//* }}} *//* }}} *//*------------------------------------------------------------------------*//* {{{ Number theoretic functions */#if MP_NUMTH/* {{{ mp_gcd(a, b, c) *//*  Like the old mp_gcd() function, except computes the GCD using the  binary algorithm due to Josef Stein in 1961 (via Knuth). */mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c){  mp_err   res;  mp_int   u, v, t;  mp_size  k = 0;  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);  if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)      return MP_RANGE;  if(mp_cmp_z(a) == MP_EQ) {    return mp_copy(b, c);  } else if(mp_cmp_z(b) == MP_EQ) {    return mp_copy(a, c);  }  if((res = mp_init(&t)) != MP_OKAY)    return res;  if((res = mp_init_copy(&u, a)) != MP_OKAY)    goto U;  if((res = mp_init_copy(&v, b)) != MP_OKAY)    goto V;  SIGN(&u) = ZPOS;  SIGN(&v) = ZPOS;  /* Divide out common factors of 2 until at least 1 of a, b is even */  while(mp_iseven(&u) && mp_iseven(&v)) {    s_mp_div_2(&u);    s_mp_div_2(&v);    ++k;  }  /* Initialize t */  if(mp_isodd(&u)) {    if((res = mp_copy(&v, &t)) != MP_OKAY)      goto CLEANUP;        /* t = -v */    if(SIGN(&v) == ZPOS)      SIGN(&t) = NEG;    else      SIGN(&t) = ZPOS;      } else {    if((res = mp_copy(&u, &t)) != MP_OKAY)      goto CLEANUP;  }  for(;;) {    while(mp_iseven(&t)) {      s_mp_div_2(&t);    }    if(mp_cmp_z(&t) == MP_GT) {      if((res = mp_copy(&t, &u)) != MP_OKAY)	goto CLEANUP;    } else {      if((res = mp_copy(&t, &v)) != MP_OKAY)	goto CLEANUP;      /* v = -t */      if(SIGN(&t) == ZPOS)	SIGN(&v) = NEG;      else	SIGN(&v) = ZPOS;    }    if((res = mp_sub(&u, &v, &t)) != MP_OKAY)      goto CLEANUP;    if(s_mp_cmp_d(&t, 0) == MP_EQ)      break;  }  s_mp_2expt(&v, k);       /* v = 2^k   */  res = mp_mul(&u, &v, c); /* c = u * v */ CLEANUP:  mp_clear(&v); V:  mp_clear(&u); U:  mp_clear(&t);  return res;} /* end mp_gcd() *//* }}} *//* {{{ mp_lcm(a, b, c) *//* We compute the least common multiple using the rule:   ab = [a, b](a, b)   ... by computing the product, and dividing out the gcd. */mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c){  mp_int  gcd, prod;  mp_err  res;  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);  /* Set up temporaries */  if((res = mp_init(&gcd)) != MP_OKAY)    return res;  if((res = mp_init(&prod)) != MP_OKAY)    goto GCD;  if((res = mp_mul(a, b, &prod)) != MP_OKAY)    goto CLEANUP;  if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)    goto CLEANUP;  res = mp_div(&prod, &gcd, c, NULL); CLEANUP:  mp_clear(&prod); GCD:  mp_clear(&gcd);  return res;} /* end mp_lcm() *//* }}} *//* {{{ mp_xgcd(a, b, g, x, y) *//*  mp_xgcd(a, b, g, x, y)  Compute g = (a, b) and values x and y satisfying Bezout's identity  (that is, ax + by = g).  This uses the binary extended GCD algorithm  based on the Stein algorithm used for mp_gcd()  See algorithm 14.61 in Handbook of Applied Cryptogrpahy. */mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y){  mp_int   gx, xc, yc, u, v, A, B, C, D;  mp_int  *clean[9];  mp_err   res;  int      last = -1;  if(mp_cmp_z(b) == 0)    return MP_RANGE;  /* Initialize all these variables we need */  MP_CHECKOK( mp_init(&u) );  clean[++last] = &u;  MP_CHECKOK( mp_init(&v) );  clean[++last] = &v;  MP_CHECKOK( mp_init(&gx) );  clean[++last] = &gx;  MP_CHECKOK( mp_init(&A) );  clean[++last] = &A;  MP_CHECKOK( mp_init(&B) );  clean[++last] = &B;  MP_CHECKOK( mp_init(&C) );  clean[++last] = &C;  MP_CHECKOK( mp_init(&D) );  clean[++last] = &D;  MP_CHECKOK( mp_init_copy(&xc, a) );  clean[++last] = &xc;  mp_abs(&xc, &xc);  MP_CHECKOK( mp_init_copy(&yc, b) );  clean[++last] = &yc;  mp_abs(&yc, &yc);  mp_set(&gx, 1);  /* Divide by two until at least one of them is odd */  while(mp_iseven(&xc) && mp_iseven(&yc)) {    mp_size nx = mp_trailing_zeros(&xc);    mp_size ny = mp_trailing_zeros(&yc);    mp_size n  = MP_MIN(nx, ny);    s_mp_div_2d(&xc,n);    s_mp_div_2d(&yc,n);    MP_CHECKOK( s_mp_mul_2d(&gx,n) );  }  mp_copy(&xc, &u);  mp_copy(&yc, &v);  mp_set(&A, 1); mp_set(&D, 1);  /* Loop through binary GCD algorithm */  do {    while(mp_iseven(&u)) {      s_mp_div_2(&u);      if(mp_iseven(&A) && mp_iseven(&B)) {	s_mp_div_2(&A); s_mp_div_2(&B);      } else {	MP_CHECKOK( mp_add(&A, &yc, &A) );	s_mp_div_2(&A);	MP_CHECKOK( mp_sub(&B, &xc, &B) );	s_mp_div_2(&B);      }    }    while(mp_iseven(&v)) {      s_mp_div_2(&v);      if(mp_iseven(&C) && mp_iseven(&D)) {	s_mp_div_2(&C); s_mp_div_2(&D);      } else {	MP_CHECKOK( mp_add(&C, &yc, &C) );	s_mp_div_2(&C);	MP_CHECKOK( mp_sub(&D, &xc, &D) );	s_mp_div_2(&D);      }    }    if(mp_cmp(&u, &v) >= 0) {      MP_CHECKOK( mp_sub(&u, &v, &u) );      MP_CHECKOK( mp_sub(&A, &C, &A) );      MP_CHECKOK( mp_sub(&B, &D, &B) );    } else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -