status_t element_invert(element_t c, element_t a) { GroupType type = a->type; EXIT_IF_NOT_SAME(a, c); if(type == ZR) { bn_t s; bn_inits(s); // compute c = (1 / a) mod n bn_gcd_ext(s, c->bn, NULL, a->bn, a->order); if(bn_sign(c->bn) == BN_NEG) bn_add(c->bn, c->bn, a->order); bn_free(s); } else if(type == G1) { g1_neg(c->g1, a->g1); } else if(type == G2) { g2_neg(c->g2, a->g2); } else if(type == GT) { gt_inv(c->gt, a->gt); } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
int inverse(bn_st * inv_in, bn_st * in, bn_st * modulus, int sizeof_mod) { // Compute the inverse of in using an extended Euclidian Algorithm // This cooresponds to the formula out = inv_in*in + useless*modulus // Where, since mod is prime, out should be equal to 1 and 1 = in*inv_in // Otherwise throws an error bn_mod_basic(in,in,modulus); bn_st out, useless; bn_new_size(&out, 2*sizeof_mod+1); bn_new_size(&useless, sizeof_mod); bn_gcd_ext(&out, inv_in, &useless, in, modulus); // Check if out is actually one bn_st is_one; bn_new_size(&is_one, sizeof_mod); bn_set_2b(&is_one, 0); // Set an integer to one if (bn_cmp(&out, &is_one) != CMP_EQ) { error_hdl(-1,"The modulus is not prime, can't calculate the inverse"); return 1; } bn_clean(&is_one); bn_clean(&out); bn_clean(&useless); return 0; }
int cp_rsa_gen_basic(rsa_t pub, rsa_t prv, int bits) { bn_t t, r; int result = STS_OK; if (pub == NULL || prv == NULL || bits == 0) { return STS_ERR; } bn_null(t); bn_null(r); TRY { bn_new(t); bn_new(r); /* Generate different primes p and q. */ do { bn_gen_prime(prv->p, bits / 2); bn_gen_prime(prv->q, bits / 2); } while (bn_cmp(prv->p, prv->q) == CMP_EQ); /* Swap p and q so that p is smaller. */ if (bn_cmp(prv->p, prv->q) == CMP_LT) { bn_copy(t, prv->p); bn_copy(prv->p, prv->q); bn_copy(prv->q, t); } bn_mul(pub->n, prv->p, prv->q); bn_copy(prv->n, pub->n); bn_sub_dig(prv->p, prv->p, 1); bn_sub_dig(prv->q, prv->q, 1); bn_mul(t, prv->p, prv->q); bn_set_2b(pub->e, 16); bn_add_dig(pub->e, pub->e, 1); bn_gcd_ext(r, prv->d, NULL, pub->e, t); if (bn_sign(prv->d) == BN_NEG) { bn_add(prv->d, prv->d, t); } if (bn_cmp_dig(r, 1) == CMP_EQ) { bn_add_dig(prv->p, prv->p, 1); bn_add_dig(prv->q, prv->q, 1); } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(t); bn_free(r); } return result; }
int cp_phpe_dec(uint8_t *out, int out_len, uint8_t *in, int in_len, bn_t n, bn_t l) { bn_t c, u, s; int size, result = STS_OK; size = bn_size_bin(n); if (in_len < 0 || in_len != 2 * size) { return STS_ERR; } bn_null(c); bn_null(u); bn_null(s); TRY { bn_new(c); bn_new(u); bn_new(s); /* Compute (c^l mod n^2) * u mod n. */ bn_sqr(s, n); bn_read_bin(c, in, in_len); bn_mxp(c, c, l, s); bn_sub_dig(c, c, 1); bn_div(c, c, n); bn_gcd_ext(s, u, NULL, l, n); if (bn_sign(u) == BN_NEG) { bn_add(u, u, n); } bn_mul(c, c, u); bn_mod(c, c, n); size = bn_size_bin(c); if (size <= out_len) { memset(out, 0, out_len); bn_write_bin(out + (out_len - size), size, c); } else { result = STS_ERR; } } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(c); bn_free(u); bn_free(s); } return result; }
// int appears on rhs status_t element_div_int(element_t c, element_t a, integer_t b) { GroupType type = a->type; EXIT_IF_NOT_SAME(c, a); LEAVE_IF( c->isInitialized != TRUE || a->isInitialized != TRUE, "uninitialized arguments."); LEAVE_IF( c->type != type, "result initialized but invalid type."); if(type == ZR) { if(bn_is_zero(b)) return ELEMENT_DIV_ZERO; // if(bn_is_one(a->bn)) { // element_set_int(a, b); // return element_invert(c, a); // not going to work // } integer_t s; bn_inits(s); // compute c = (1 / b) mod order bn_gcd_ext(s, c->bn, NULL, b, a->order); if(bn_sign(c->bn) == BN_NEG) bn_add(c->bn, c->bn, a->order); if(bn_is_one(a->bn) && bn_sign(a->bn) == BN_POS) { bn_free(s); return ELEMENT_OK; } // remainder of ((a * c) / order) // c = (a * c) / order (remainder only) bn_mul(s, a->bn, c->bn); bn_div_rem(s, c->bn, s, a->order); // if(bn_sign(c->bn) == BN_NEG) bn_add(c->bn, c->bn, a->order); bn_free(s); // bn_div(c->bn, a->bn, b); // bn_mod(c->bn, c->bn, c->order); } else if(type == G1 || type == G2 || type == GT) { if(bn_is_one(b)) { return element_set(c, a); } // TODO: other cases: b > 1 (ZR)? } else { return ELEMENT_INVALID_TYPES; } return ELEMENT_OK; }
int cp_bbs_sig(g1_t s, uint8_t *msg, int len, int hash, bn_t d) { bn_t m, n, r; uint8_t h[MD_LEN]; int result = STS_OK; bn_null(m); bn_null(n); bn_null(r); TRY { bn_new(m); bn_new(n); bn_new(r); g1_get_ord(n); /* m = H(msg). */ if (hash) { bn_read_bin(m, msg, len); } else { md_map(h, msg, len); bn_read_bin(m, h, MD_LEN); } bn_mod(m, m, n); /* m = 1/(m + d) mod n. */ bn_add(m, m, d); bn_gcd_ext(r, m, NULL, m, n); if (bn_sign(m) == BN_NEG) { bn_add(m, m, n); } /* s = 1/(m+d) * g1. */ g1_mul_gen(s, m); } CATCH_ANY { result = STS_ERR; } FINALLY { bn_free(m); bn_free(n); bn_free(r); } return result; }