BIGNUM* Commit(const_ProductStatement st, const BIGNUM* m1, const BIGNUM* m2) { unsigned char digest[SHA_DIGEST_LENGTH]; SHA_CTX sha; CHECK_CALL(SHA1_Init(&sha)); AddBignumToHash(&sha, IntegerGroup_GetP(st->group)); AddBignumToHash(&sha, IntegerGroup_GetQ(st->group)); AddBignumToHash(&sha, IntegerGroup_GetG(st->group)); AddBignumToHash(&sha, IntegerGroup_GetH(st->group)); AddBignumToHash(&sha, st->commit_a); AddBignumToHash(&sha, st->commit_b); AddBignumToHash(&sha, st->commit_c); AddBignumToHash(&sha, m1); AddBignumToHash(&sha, m2); CHECK_CALL(SHA1_Final(digest, &sha)); BIGNUM* result = BN_bin2bn(digest, SHA_DIGEST_LENGTH, NULL); CHECK_CALL(result); CHECK_CALL(BN_mod(result, result, IntegerGroup_GetQ(st->group), IntegerGroup_GetCtx(st->group))); return result; }
EVP_PKEY* CreateRsaKey(const_RsaDevice d) { BN_CTX* ctx = IntegerGroup_GetCtx(RsaParams_GetGroup(d->params)); // phi(n) = (p-1)(q-1) BIGNUM *phi_n, *pm, *qm; phi_n = BN_new(); CHECK_CALL(phi_n); CHECK_CALL(pm = BN_dup(d->p)); CHECK_CALL(qm = BN_dup(d->q)); CHECK_CALL(BN_sub_word(pm, 1)); CHECK_CALL(BN_sub_word(qm, 1)); CHECK_CALL(BN_mul(phi_n, pm, qm, ctx)); EVP_PKEY *evp = EVP_PKEY_new(); RSA *rsa = RSA_new(); CHECK_CALL(evp); CHECK_CALL(rsa); CHECK_CALL(rsa->n = BN_dup(d->n)); // public modulus CHECK_CALL(rsa->e = BN_new()); // public exponent BN_set_word(rsa->e, RsaEncryptionExponent); rsa->d = BN_new(); // private exponent CHECK_CALL(rsa->d); CHECK_CALL(BN_mod_inverse(rsa->d, rsa->e, phi_n, ctx)); CHECK_CALL(rsa->p = BN_dup(d->p)); // secret prime factor CHECK_CALL(rsa->q = BN_dup(d->q)); // secret prime factor rsa->dmp1 = BN_new(); // d mod (p-1) CHECK_CALL(rsa->dmp1); CHECK_CALL(BN_mod(rsa->dmp1, rsa->d, pm, ctx)); rsa->dmq1 = BN_new(); // d mod (q-1) CHECK_CALL(rsa->dmq1); CHECK_CALL(BN_mod(rsa->dmq1, rsa->d, qm, ctx)); rsa->iqmp = BN_new(); // q^-1 mod p CHECK_CALL(rsa->iqmp); CHECK_CALL(BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)); CHECK_CALL(EVP_PKEY_set1_RSA(evp, rsa)); ASSERT(RSA_check_key(rsa)); BN_clear_free(phi_n); BN_clear_free(pm); BN_clear_free(qm); return evp; }
bool ProductEvidence_Verify(const_ProductEvidence ev, const_ProductStatement st) { const BIGNUM* g = IntegerGroup_GetG(st->group); const BIGNUM* h = IntegerGroup_GetH(st->group); const BIGNUM* p = IntegerGroup_GetP(st->group); BN_CTX* ctx = IntegerGroup_GetCtx(st->group); BIGNUM *tmp = BN_new(); // Recompute commitments // m1' = (g^z h^w1) / A^c BIGNUM* m1 = IntegerGroup_CascadeExponentiate(st->group, g, ev->z, h, ev->w1); CHECK_CALL(m1); CHECK_CALL(BN_copy(tmp, st->commit_a)); CHECK_CALL(BN_mod_exp(tmp, tmp, ev->c, p, ctx)); CHECK_CALL(BN_mod_inverse(tmp, tmp, p, ctx)); CHECK_CALL(BN_mod_mul(m1, m1, tmp, p, ctx)); // m2' = (B^z h^w2) / C^c BIGNUM* m2 = IntegerGroup_CascadeExponentiate(st->group, st->commit_b, ev->z, h, ev->w2); CHECK_CALL(m2); CHECK_CALL(BN_copy(tmp, st->commit_c)); CHECK_CALL(BN_mod_exp(tmp, tmp, ev->c, p, ctx)); CHECK_CALL(BN_mod_inverse(tmp, tmp, p, ctx)); CHECK_CALL(BN_mod_mul(m2, m2, tmp, p, ctx)); BN_clear_free(tmp); // Check challenge // c =? H(g, h, q, p, A, B, C, m1', m2') BIGNUM *c_prime = Commit(st, m1, m2); BN_free(m1); BN_free(m2); bool retval = !BN_cmp(ev->c, c_prime); BN_clear_free(c_prime); return retval; }
ProductEvidence ProductEvidence_New(ProductStatement st, const BIGNUM *a, const BIGNUM *r_a, const BIGNUM *r_b, const BIGNUM *r_c) { ProductEvidence ev = safe_malloc(sizeof(*ev)); const BIGNUM* g = IntegerGroup_GetG(st->group); const BIGNUM* h = IntegerGroup_GetH(st->group); const BIGNUM* q = IntegerGroup_GetQ(st->group); BN_CTX* ctx = IntegerGroup_GetCtx(st->group); // A = g^a h^{r_a} // B = g^b h^{r_b} // C = g^{ab} h^{r_c} // r_prod = r_c - a*r_b BIGNUM* r_prod; CHECK_CALL(r_prod = BN_dup(a)); CHECK_CALL(BN_mod_mul(r_prod, r_prod, r_b, q, ctx)); CHECK_CALL(BN_mod_sub(r_prod, r_c, r_prod, q, ctx)); // == Commitment == // x, s1, s2 in [0, q) BIGNUM *x = IntegerGroup_RandomExponent(st->group); BIGNUM *s1 = IntegerGroup_RandomExponent(st->group); BIGNUM *s2 = IntegerGroup_RandomExponent(st->group); CHECK_CALL(x); CHECK_CALL(s1); CHECK_CALL(s2); // m1 = g^x h^s1 BIGNUM* m1 = IntegerGroup_CascadeExponentiate(st->group, g, x, h, s1); CHECK_CALL(m1); // m2 = B^x h^s2 BIGNUM* m2 = IntegerGroup_CascadeExponentiate(st->group, st->commit_b, x, h, s2); CHECK_CALL(m2); // == Challenge == // c = H(g, h, q, p, A, B, C, m1, m2) ev->c = Commit(st, m1, m2); // == Response == // z = x + ca mod q ev->z = BN_dup(ev->c); CHECK_CALL(ev->z); CHECK_CALL(BN_mod_mul(ev->z, ev->z, a, q, ctx)); CHECK_CALL(BN_mod_add(ev->z, ev->z, x, q, ctx)); // w1 = s1 + (c r_a) mod q ev->w1 = BN_dup(r_a); CHECK_CALL(ev->w1); CHECK_CALL(BN_mod_mul(ev->w1, ev->w1, ev->c, q, ctx)); CHECK_CALL(BN_mod_add(ev->w1, ev->w1, s1, q, ctx)); // w2 = s2 + (c r_prod) mod q ev->w2 = BN_dup(r_prod); CHECK_CALL(ev->w2); CHECK_CALL(BN_mod_mul(ev->w2, ev->w2, ev->c, q, ctx)); CHECK_CALL(BN_mod_add(ev->w2, ev->w2, s2, q, ctx)); // proof is (c, z, w1, w2) BN_free(m1); BN_free(m2); BN_clear_free(x); BN_clear_free(s1); BN_clear_free(s2); BN_clear_free(r_prod); return ev; }