935 lines
41 KiB
C
935 lines
41 KiB
C
/* Cryptic -- Cryptographic tools and protocols
|
|
* Copyright (C) 2010 Mikaël Ates <mates@entrouvert.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <glib.h>
|
|
#include <glib-object.h>
|
|
#include <openssl/bn.h>
|
|
#include <openssl/bio.h>
|
|
|
|
#include "../../errors.h"
|
|
#include "../../utils.h"
|
|
|
|
#include "../pok_schnorr/schnorr_zkpk.h"
|
|
#include "../proof_range/proof_range_in_qrg.h"
|
|
|
|
/*****************************************************************************/
|
|
/* private methods */
|
|
/*****************************************************************************/
|
|
|
|
static GObjectClass *parent_class = NULL;
|
|
|
|
/*****************************************************************************/
|
|
/* overridden parent class methods */
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
dispose(GObject *object)
|
|
{
|
|
CrypticProofrangeQrg *pr = CRYPTIC_PROOFRANGEQRG(object);
|
|
|
|
int i;
|
|
|
|
cryptic_release_bn(pr->modulus);
|
|
cryptic_release_bn(pr->m);
|
|
cryptic_release_bn(pr->b);
|
|
cryptic_release_bn(pr->delta);
|
|
cryptic_release_bn(pr->randDLRepDelta);
|
|
cryptic_release_bn(pr->randQ);
|
|
cryptic_release_bn(pr->Q);
|
|
cryptic_release_bn(pr->challenge);
|
|
if(pr->tabBases){
|
|
for(i=0;i<2;i++){
|
|
cryptic_release_bn(pr->tabBases[i]);
|
|
}
|
|
}
|
|
if(pr->tabRandDLRepSqrRoot){
|
|
for(i=0;i<4;i++){
|
|
cryptic_release_bn(pr->tabRandDLRepSqrRoot[i]);
|
|
}
|
|
}
|
|
if(pr->dlreps){
|
|
for(i=0;i<5;i++){
|
|
cryptic_release_bn(pr->dlreps[i]);
|
|
}
|
|
}
|
|
if(pr->commitments){
|
|
for(i=0;i<6;i++){
|
|
cryptic_release_bn(pr->commitments[i]);
|
|
}
|
|
}
|
|
if(pr->responses){
|
|
for(i=0;i<11;i++){
|
|
cryptic_release_bn(pr->responses[i]);
|
|
}
|
|
}
|
|
cryptic_release(pr->tabBases);
|
|
cryptic_release(pr->tabRandDLRepSqrRoot);
|
|
cryptic_release(pr->dlreps);
|
|
cryptic_release(pr->commitments);
|
|
cryptic_release(pr->responses);
|
|
|
|
cryptic_release_gobject(pr->pokSqrRoot1);
|
|
cryptic_release_gobject(pr->pokSqrRoot2);
|
|
cryptic_release_gobject(pr->pokSqrRoot3);
|
|
cryptic_release_gobject(pr->pokSqrRoot4);
|
|
cryptic_release_gobject(pr->pokDelta);
|
|
|
|
cryptic_release_gobject(pr->di);
|
|
|
|
G_OBJECT_CLASS(parent_class)->dispose(G_OBJECT(pr));
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* instance and class init functions */
|
|
/*****************************************************************************/
|
|
|
|
static void
|
|
instance_init(CrypticProofrangeQrg *pr)
|
|
{
|
|
pr->modulus = NULL;
|
|
pr->m = NULL;
|
|
pr->b = NULL;
|
|
pr->delta = NULL;
|
|
pr->randDLRepDelta = NULL;
|
|
pr->randQ = NULL;
|
|
pr->Q = NULL;
|
|
pr->challenge = NULL;
|
|
pr->tabBases = NULL;
|
|
pr->tabRandDLRepSqrRoot = NULL;
|
|
pr->dlreps = NULL;
|
|
pr->commitments = NULL;
|
|
pr->responses = NULL;
|
|
pr->pokSqrRoot1 = NULL;
|
|
pr->pokSqrRoot2 = NULL;
|
|
pr->pokSqrRoot3 = NULL;
|
|
pr->pokSqrRoot4 = NULL;
|
|
pr->pokDelta = NULL;
|
|
pr->di = NULL;
|
|
}
|
|
|
|
static void
|
|
class_init(CrypticProofrangeQrgClass *klass)
|
|
{
|
|
parent_class = g_type_class_peek_parent(klass);
|
|
G_OBJECT_CLASS(klass)->dispose = dispose;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* public methods */
|
|
/*****************************************************************************/
|
|
|
|
GType
|
|
cryptic_proofrange_qrg_get_type()
|
|
{
|
|
static GType this_type = 0;
|
|
if (!this_type) {
|
|
static const GTypeInfo this_info = {
|
|
sizeof (CrypticProofrangeQrgClass),
|
|
NULL,
|
|
NULL,
|
|
(GClassInitFunc) class_init,
|
|
NULL,
|
|
NULL,
|
|
sizeof(CrypticProofrangeQrg),
|
|
0,
|
|
(GInstanceInitFunc) instance_init,
|
|
NULL
|
|
};
|
|
this_type = g_type_register_static(G_TYPE_OBJECT,
|
|
"CrypticProofrangeQrg", &this_info, 0);
|
|
}
|
|
return this_type;
|
|
}
|
|
|
|
/**
|
|
* cryptic_proofrange_qrg_new:
|
|
* @base1: First base used for the DL representation.
|
|
* @base2: Second base used for the DL representation.
|
|
* @modulus: Modulus of the group.
|
|
*
|
|
* Creates a new #CrypticProofrangeQrg.
|
|
*
|
|
* Return value: a newly created #CrypticProofrangeQrg object; or NULL if an error
|
|
* occured
|
|
**/
|
|
CrypticProofrangeQrg*
|
|
cryptic_proofrange_qrg_new(BIGNUM *base1, BIGNUM *base2, BIGNUM *modulus)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
CrypticProofrangeQrg *pr;
|
|
pr = g_object_new(CRYPTIC_TYPE_PROOFRANGEQRG, NULL);
|
|
|
|
int i;
|
|
|
|
cryptic_release(pr->tabBases);
|
|
pr->tabBases = g_malloc0(2 * sizeof (**pr->tabBases));
|
|
for(i=0; i<2; i++){
|
|
pr->tabBases[i] = NULL;
|
|
}
|
|
cryptic_release(pr->tabRandDLRepSqrRoot);
|
|
pr->tabRandDLRepSqrRoot = g_malloc0(4 * sizeof (**pr->tabRandDLRepSqrRoot));
|
|
for(i=0; i<4; i++){
|
|
pr->tabRandDLRepSqrRoot[i] = NULL;
|
|
}
|
|
cryptic_release(pr->dlreps);
|
|
pr->dlreps = g_malloc0(5 * sizeof (**pr->dlreps));
|
|
for(i=0; i<5; i++){
|
|
pr->dlreps[i] = NULL;
|
|
}
|
|
cryptic_release(pr->commitments);
|
|
pr->commitments = g_malloc0(6 * sizeof (**pr->commitments));
|
|
for(i=0; i<6; i++){
|
|
pr->commitments[i] = NULL;
|
|
}
|
|
cryptic_release(pr->responses);
|
|
pr->responses = g_malloc0(11 * sizeof (**pr->responses));
|
|
for(i=0; i<11; i++){
|
|
pr->responses[i] = NULL;
|
|
}
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->tabBases[0] = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->tabBases[0],base1));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->tabBases[1] = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->tabBases[1],base2));
|
|
|
|
cryptic_release_bn(pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->modulus = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->modulus, modulus));
|
|
|
|
return pr;
|
|
cleanup:
|
|
cryptic_release_gobject(pr);
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/**
|
|
* cryptic_proofrange_qrg_round1:
|
|
* @rel: inequality to prove.
|
|
* @m: quantity on which the range proof is led.
|
|
* @b: quantity of comparison.
|
|
* @random_m: Random for m.
|
|
* @rand1: size of the random for proof of the first square.
|
|
* @rand2: size of the random for proof of the second square.
|
|
* @rand3: size of the random for proof of the third square.
|
|
* @rand4: size of the random for proof of the forth square.
|
|
*
|
|
* Lead a range proof relying on the interactive Schnorr ZKPK. Round1 for committing.
|
|
*
|
|
* Return value: #CRYPTIC_NO_ERROR if successful, an error code otherwise.
|
|
*/
|
|
int
|
|
cryptic_proofrange_qrg_round1(CrypticProofrangeQrg *pr, int rel, BIGNUM *m, BIGNUM *b, BIGNUM *random_m, int lg_sec_param, int lg_zk_sec_param, int lg_challenge)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
int i;
|
|
int neg = 0;
|
|
BIGNUM *tmp = NULL;
|
|
BIGNUM *tab_rand[2];
|
|
tab_rand[0] = NULL;
|
|
tab_rand[1] = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
BN_MONT_CTX *mont = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(pr->modulus != NULL,
|
|
CRYPTIC_PROOF_RANGE_STRUCTURE_NOT_INIT);
|
|
goto_cleanup_if_fail_with_rc_with_warning(m != NULL,
|
|
CRYPTIC_PROOF_RANGE_STRUCTURE_NOT_INIT);
|
|
goto_cleanup_if_fail_with_rc_with_warning(b != NULL,
|
|
CRYPTIC_PROOF_RANGE_NO_BOUND);
|
|
|
|
if(lg_sec_param<CRYPTIC_PROOF_RANGE_TEST_SEC_PARAM){
|
|
lg_sec_param = CRYPTIC_PROOF_RANGE_TEST_SEC_PARAM;
|
|
}
|
|
if(lg_zk_sec_param<CRYPTIC_PROOF_RANGE_TEST_ZK_SEC_PARAM){
|
|
lg_zk_sec_param = CRYPTIC_PROOF_RANGE_TEST_ZK_SEC_PARAM;
|
|
}
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(lg_challenge >= CRYPTIC_PROOF_RANGE_TEST_CHALLENGE_MIN_SIZE,
|
|
CRYPTIC_PROOF_GENERIC_CHALLENGE_SIZE_NOT_VALID);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tab_rand[0] = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tab_rand[1] = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(mont=BN_MONT_CTX_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_MONT_CTX_set(mont,pr->modulus,ctx));
|
|
|
|
/*****************************
|
|
* Compute delta
|
|
******************************/
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->delta = BN_new());
|
|
|
|
switch (rel) {
|
|
case CRYPTIC_PROOF_RANGE_LTE:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,b,m) == 1); // b-m
|
|
neg = 1;
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_LT:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,b,m) == 1); // b-m-1
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,pr->delta,BN_value_one()) == 1);
|
|
neg = 1;
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_GTE:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,m,b) == 1); // m-b
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_GT:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,m,b) == 1); // m-b-1
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,pr->delta,BN_value_one()) == 1);
|
|
break;
|
|
default:
|
|
rc = CRYPTIC_PROOF_RANGE_RELATION_UNKNOWN;
|
|
goto cleanup;
|
|
}
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(!BN_is_negative(pr->delta),
|
|
CRYPTIC_PROOF_RANGE_DELTA_NEGATIVE);
|
|
|
|
/*****************************
|
|
* Decomposition
|
|
******************************/
|
|
|
|
cryptic_release_bn(pr->m);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->m = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->m,m));
|
|
cryptic_release_bn(pr->b);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->b = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->b,b));
|
|
|
|
pr->di = cryptic_decompose_integer_new(pr->delta);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(pr->di >= 0 && cryptic_decompose_integer_verify_decomposition(pr->di,pr->delta) == 1,
|
|
CRYPTIC_PROOF_RANGE_DECOMPOSITION_FAILED);
|
|
|
|
/* IBM: RZ3730 (#99740) 03/19/2009 */
|
|
/* rdelta, ri : rand1 = ln + l_zk_sec_param */
|
|
/* qi : rand2 = lm + l_challenge + l_zk_sec_param */
|
|
/* zdelta, zi : rand3 = lm + l_challenge + 2*l_zk_sec_param */
|
|
/* rrho : rand4 = ln + lm + 2*l_sec_param + 2*l_zk_sec_param + 3 */
|
|
|
|
int lg_modulus = BN_num_bits(pr->modulus);
|
|
int lg_quantity = lg_challenge;
|
|
|
|
int rand1 = lg_modulus + lg_zk_sec_param;
|
|
int rand2 = lg_quantity + lg_challenge + lg_zk_sec_param;
|
|
int rand3 = lg_quantity + lg_challenge + 2*lg_zk_sec_param;
|
|
int rand4 = lg_modulus + lg_quantity + 2*lg_sec_param + 2*lg_zk_sec_param + 3;
|
|
|
|
/*****************************
|
|
* Build dlrep
|
|
******************************/
|
|
|
|
for(i=0;i<4;i++){
|
|
cryptic_release_bn(pr->tabRandDLRepSqrRoot[i]);
|
|
cryptic_release_bn(pr->dlreps[i]);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->tabRandDLRepSqrRoot[i] = BN_new()); //random to dlrep the square roots of Delta
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->dlreps[i] = BN_new()); //dlrep of the square roots of Delta (Ti)
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(pr->tabRandDLRepSqrRoot[i],rand1) == 0);
|
|
switch (i){
|
|
case 0: goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(pr->dlreps[i],pr->tabBases[0],cryptic_getSqrRoot1(pr->di),pr->modulus,ctx,mont) == 1); break;
|
|
case 1: goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(pr->dlreps[i],pr->tabBases[0],cryptic_getSqrRoot2(pr->di),pr->modulus,ctx,mont) == 1); break;
|
|
case 2: goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(pr->dlreps[i],pr->tabBases[0],cryptic_getSqrRoot3(pr->di),pr->modulus,ctx,mont) == 1); break;
|
|
case 3: goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(pr->dlreps[i],pr->tabBases[0],cryptic_getSqrRoot4(pr->di),pr->modulus,ctx,mont) == 1); break;
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->tabBases[1],pr->tabRandDLRepSqrRoot[i],pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->dlreps[i],pr->dlreps[i],tmp,pr->modulus,ctx) == 1);
|
|
}
|
|
|
|
cryptic_release_bn(pr->randDLRepDelta);
|
|
cryptic_release_bn(pr->dlreps[4]);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->randDLRepDelta = BN_new()); //random to dlrep Delta
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->dlreps[4] = BN_new()); //dlrep Delta (Td)
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(pr->randDLRepDelta,rand1) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(pr->dlreps[4],pr->tabBases[0],pr->delta,pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->tabBases[1],pr->randDLRepDelta,pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->dlreps[4],pr->dlreps[4],tmp,pr->modulus,ctx) == 1);
|
|
|
|
/*****************************
|
|
* Compute commitments
|
|
******************************/
|
|
|
|
pr->pokSqrRoot1 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[0],rand2) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[1],rand3) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round1_randoms_chosen(pr->pokSqrRoot1,tab_rand) == 0);
|
|
|
|
pr->pokSqrRoot2 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[0],rand2) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[1],rand3) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round1_randoms_chosen(pr->pokSqrRoot2,tab_rand) == 0);
|
|
|
|
pr->pokSqrRoot3 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[0],rand2) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[1],rand3) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round1_randoms_chosen(pr->pokSqrRoot3,tab_rand) == 0);
|
|
|
|
pr->pokSqrRoot4 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[0],rand2) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[1],rand3) == 0);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round1_randoms_chosen(pr->pokSqrRoot4,tab_rand) == 0);
|
|
|
|
if(neg){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tmp,pr->tabBases[1]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_inverse(pr->tabBases[1],pr->tabBases[1],pr->modulus,ctx));
|
|
}
|
|
|
|
pr->pokDelta = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_rand[0],random_m)); //r_m
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_find_random(tab_rand[1],rand3) == 0); //z_delta
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round1_randoms_chosen(pr->pokDelta,tab_rand) == 0);
|
|
if(neg) goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->tabBases[1],tmp));
|
|
|
|
/*****************************
|
|
* Compute Q
|
|
******************************/
|
|
|
|
cryptic_release_bn(pr->randQ);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->randQ = BN_new());
|
|
cryptic_check_good_rc(cryptic_find_random(pr->randQ,rand4)); //r_rho
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->Q = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(pr->Q,pr->dlreps[0],cryptic_zkpk_schnorr_get_i_random(pr->pokSqrRoot1, 0),pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->dlreps[1],cryptic_zkpk_schnorr_get_i_random(pr->pokSqrRoot2, 0),pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->dlreps[2],cryptic_zkpk_schnorr_get_i_random(pr->pokSqrRoot3, 0),pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->dlreps[3],cryptic_zkpk_schnorr_get_i_random(pr->pokSqrRoot4, 0),pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->tabBases[1],pr->randQ,pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_mont(mont);
|
|
cryptic_release_bn(tab_rand[1]);
|
|
cryptic_release_bn(tab_rand[0]);
|
|
cryptic_release_bn(tmp);
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* cryptic_proofrange_qrg_round1:
|
|
* @challenge: challenge for interactive, hash for non interactive proofs.
|
|
*
|
|
* Round2 for response.
|
|
*
|
|
* Return value: #CRYPTIC_NO_ERROR if successful, an error code otherwise.
|
|
*/
|
|
int
|
|
cryptic_proofrange_qrg_round2(CrypticProofrangeQrg *pr, BIGNUM *challenge)
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
BIGNUM *tmp = NULL;
|
|
BIGNUM *tab_qty[2];
|
|
tab_qty[0] = NULL;
|
|
tab_qty[1] = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(pr->modulus != NULL,
|
|
CRYPTIC_PROOF_RANGE_STRUCTURE_NOT_INIT);
|
|
goto_cleanup_if_fail_with_rc_with_warning(pr->Q != NULL,
|
|
CRYPTIC_PROOF_RANGE_INTERACTIVE_ROUND_1_UNCOMPLETE);
|
|
goto_cleanup_if_fail_with_rc_with_warning(challenge != NULL,
|
|
CRYPTIC_PROOF_RANGE_INTERACTIVE_ROUND_2_NO_CHALLENGE);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->challenge = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->challenge,challenge));
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tab_qty[0] = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tab_qty[1] = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
|
|
/*****************************
|
|
* Compute responses
|
|
******************************/
|
|
|
|
/* S_u_1 = pr->pokSqrRoot1->random[0] + c.u_1 */
|
|
/* S_r_1 = pr->pokSqrRoot1->random[1] + c.r_1 */
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[0],cryptic_getSqrRoot1(pr->di)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[1],pr->tabRandDLRepSqrRoot[0]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round2_without_order(pr->pokSqrRoot1,pr->challenge,tab_qty) == 0);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[0],cryptic_getSqrRoot2(pr->di)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[1],pr->tabRandDLRepSqrRoot[1]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round2_without_order(pr->pokSqrRoot2,pr->challenge,tab_qty) == 0);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[0],cryptic_getSqrRoot3(pr->di)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[1],pr->tabRandDLRepSqrRoot[2]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round2_without_order(pr->pokSqrRoot3,pr->challenge,tab_qty) == 0);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[0],cryptic_getSqrRoot4(pr->di)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[1],pr->tabRandDLRepSqrRoot[3]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round2_without_order(pr->pokSqrRoot4,pr->challenge,tab_qty) == 0);
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[0],pr->m));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tab_qty[1],pr->randDLRepDelta));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(cryptic_zkpk_schnorr_round2_without_order(pr->pokDelta,pr->challenge,tab_qty) == 0);
|
|
|
|
cryptic_release_bn(pr->responserho);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->responserho = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(tmp,cryptic_getSqrRoot1(pr->di),pr->tabRandDLRepSqrRoot[0],ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(pr->responserho,cryptic_getSqrRoot2(pr->di),pr->tabRandDLRepSqrRoot[1],ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(pr->responserho,tmp,pr->responserho) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(tmp,cryptic_getSqrRoot3(pr->di),pr->tabRandDLRepSqrRoot[2],ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(pr->responserho,tmp,pr->responserho) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(tmp,cryptic_getSqrRoot4(pr->di),pr->tabRandDLRepSqrRoot[3],ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(pr->responserho,tmp,pr->responserho) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->responserho,pr->randDLRepDelta,pr->responserho) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mul(pr->responserho,pr->responserho,pr->challenge,ctx) == 1);
|
|
/* s = r - cx */
|
|
//goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->responserho,pr->randQ,pr->responserho) == 1);
|
|
/* s = r + cx */
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(pr->responserho,pr->randQ,pr->responserho) == 1);
|
|
|
|
int i;
|
|
for(i=0;i<11;i++){
|
|
cryptic_release_bn(pr->responses[i]);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->responses[i] = BN_new());
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[0],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot1,0)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[1],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot1,1)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[2],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot2,0)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[3],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot2,1)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[4],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot3,0)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[5],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot3,1)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[6],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot4,0)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[7],cryptic_zkpk_schnorr_get_i_response(pr->pokSqrRoot4,1)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[8],cryptic_zkpk_schnorr_get_i_response(pr->pokDelta,0)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[9],cryptic_zkpk_schnorr_get_i_response(pr->pokDelta,1)));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->responses[10],pr->responserho));
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_bn(tmp);
|
|
if(tab_qty){
|
|
int i;
|
|
for(i=0;i<2;i++){
|
|
cryptic_release_bn(tab_qty[i]);
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* cryptic_proofrange_qrg_verify_interactive_proof:
|
|
* @rel: inequality to prove.
|
|
* @b: quantity of comparison.
|
|
* @dlreps: Representation proved.
|
|
* @commitments: Commitments.
|
|
* @challenge: Challenge.
|
|
* @responses: Responses of the proof.
|
|
*
|
|
* Verify a range proof relying on the interactive Schnorr ZKPK.
|
|
*
|
|
* Return value: 1 if proof is successful, an error code otherwise.
|
|
*/
|
|
int
|
|
cryptic_proofrange_qrg_verify_interactive_proof(CrypticProofrangeQrg *pr,
|
|
int rel,
|
|
BIGNUM *b,
|
|
BIGNUM **dlreps, //T1, T2, T3, T4, T5, Tdelta
|
|
BIGNUM **commitments, //t1, t2, t3, t4, t5, tdelta, tQ
|
|
BIGNUM *challenge, //c
|
|
BIGNUM **responses) //su1, zu1, su2, zu2, su3, zu3, su4, zu4, srho
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
int i;
|
|
int neg = 0;
|
|
BIGNUM *tmp = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
BN_MONT_CTX *mont = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(pr->modulus != NULL,
|
|
CRYPTIC_PROOF_RANGE_STRUCTURE_NOT_INIT);
|
|
goto_cleanup_if_fail_with_rc_with_warning(b != NULL,
|
|
CRYPTIC_PROOF_RANGE_NO_BOUND);
|
|
|
|
cryptic_release_bn(pr->delta);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->delta = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(mont=BN_MONT_CTX_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_MONT_CTX_set(mont,pr->modulus,ctx));
|
|
|
|
/*****************************
|
|
* Compute delta
|
|
******************************/
|
|
|
|
switch (rel) {
|
|
case CRYPTIC_PROOF_RANGE_LTE:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
neg = 1;
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_LT:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,pr->delta,BN_value_one()) == 1);
|
|
neg = 1;
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_GTE:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_GT:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(pr->delta,pr->delta,BN_value_one()) == 1);
|
|
break;
|
|
default:
|
|
rc = CRYPTIC_PROOF_RANGE_RELATION_UNKNOWN;
|
|
goto cleanup;
|
|
}
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(!BN_is_negative(pr->delta),
|
|
CRYPTIC_PROOF_RANGE_DELTA_NEGATIVE);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_TAB_DLREPS_EMPTY);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[0] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_FIRST_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[1] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_SECOND_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[2] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_THIRD_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[3] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_FORTH_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[4] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_DELTA_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(commitments != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_TAB_COMMITMENTS_EMPTY);
|
|
goto_cleanup_if_fail_with_rc_with_warning(commitments[0] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_COMMIT_FIRST_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(commitments[1] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_COMMIT_SECOND_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(commitments[2] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_COMMIT_THIRD_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(commitments[3] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_COMMIT_FORTH_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(commitments[4] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_COMMIT_DELTA_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(commitments[5] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_COMMIT_Q_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(challenge != NULL,
|
|
CRYPTIC_PROOF_GENERIC_CHALLENGE_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_TAB_RESPONSES_EMPTY);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[0] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FIRST_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[1] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FIRST_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[2] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_SECOND_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[3] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_SECOND_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[4] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_THIRD_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[5] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_THIRD_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[6] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FORTH_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[7] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FORTH_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[8] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_DELTA_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[9] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_DELTA_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[10] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_RHO_MISSING);
|
|
|
|
pr->pokSqrRoot1 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning(
|
|
cryptic_zkpk_schnorr_verify_interactive_proof(pr->pokSqrRoot1, dlreps[0], commitments[0], challenge, responses) == 1,
|
|
CRYPTIC_PROOF_RANGE_VERIFICATION_FAILURE);
|
|
pr->pokSqrRoot2 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning(
|
|
cryptic_zkpk_schnorr_verify_interactive_proof(pr->pokSqrRoot2, dlreps[1], commitments[1], challenge, responses+2) == 1,
|
|
CRYPTIC_PROOF_RANGE_VERIFICATION_FAILURE);
|
|
pr->pokSqrRoot3 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning(
|
|
cryptic_zkpk_schnorr_verify_interactive_proof(pr->pokSqrRoot3, dlreps[2], commitments[2], challenge, responses+4) == 1,
|
|
CRYPTIC_PROOF_RANGE_VERIFICATION_FAILURE);
|
|
pr->pokSqrRoot4 = cryptic_zkpk_schnorr_new(pr->tabBases, 2,pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning(
|
|
cryptic_zkpk_schnorr_verify_interactive_proof(pr->pokSqrRoot4, dlreps[3], commitments[3], challenge, responses+6) == 1,
|
|
CRYPTIC_PROOF_RANGE_VERIFICATION_FAILURE);
|
|
|
|
cryptic_release_bn(pr->dlreps[4]);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->dlreps[4] = BN_new());
|
|
if(neg){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_inverse(pr->dlreps[4],dlreps[4],pr->modulus,ctx));
|
|
}else{
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->dlreps[4],dlreps[4]));
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->tabBases[0],pr->delta,pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->dlreps[4],pr->dlreps[4],tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->dlreps[4],challenge,pr->modulus,ctx,mont) == 1);
|
|
|
|
if(neg){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tmp,pr->tabBases[1]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_inverse(pr->tabBases[1],pr->tabBases[1],pr->modulus,ctx));
|
|
}
|
|
pr->pokDelta = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail_with_rc_with_warning(
|
|
cryptic_zkpk_schnorr_verify_interactive_proof(pr->pokDelta,pr->dlreps[4], commitments[4],challenge,responses+8) == 1,
|
|
CRYPTIC_PROOF_RANGE_VERIFICATION_FAILURE);
|
|
|
|
if(neg) goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->tabBases[1],tmp));
|
|
|
|
cryptic_release_bn(pr->Q);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->Q = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_inverse(tmp,dlreps[4],pr->modulus,ctx)); /* Comment for s = r - cx */
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(pr->Q,tmp,challenge,pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,dlreps[0],responses[0],pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,dlreps[1],responses[2],pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,dlreps[2],responses[4],pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,dlreps[3],responses[6],pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->tabBases[1],responses[10],pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->Q,pr->Q,tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning(BN_ucmp(pr->Q,commitments[5]) == 0,
|
|
CRYPTIC_PROOF_RANGE_VERIFICATION_FAILURE);
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_mont(mont);
|
|
cryptic_release_bn(tmp);
|
|
if(rc == CRYPTIC_NO_ERROR) return 1;
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* cryptic_proofrange_qrg_verify_noninteractive_proof:
|
|
* @rel: inequality to prove.
|
|
* @b: quantity of comparison.
|
|
* @dlreps: Representation proved.
|
|
* @hash: hash.
|
|
* @responses: Responses of the proof.
|
|
*
|
|
* Verify a range proof relying on the interactive Schnorr ZKPK.
|
|
*
|
|
* Return value: 1 if proof is successful, an error code otherwise.
|
|
*/
|
|
int
|
|
cryptic_proofrange_qrg_verify_noninteractive_proof(CrypticProofrangeQrg *pr,
|
|
int rel,
|
|
BIGNUM *b,
|
|
BIGNUM **dlreps, //T1, T2, T3, T4, T5, Tdelta
|
|
BIGNUM *hash, //hash
|
|
BIGNUM **responses) //su1, zu1, su2, zu2, su3, zu3, su4, zu4, srho
|
|
{
|
|
int rc = CRYPTIC_ERROR_UNDEFINED;
|
|
|
|
int i;
|
|
int neg = 0;
|
|
BIGNUM *tmp = NULL;
|
|
BN_CTX *ctx = NULL;
|
|
BN_MONT_CTX *mont = NULL;
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(pr->modulus != NULL,
|
|
CRYPTIC_PROOF_RANGE_STRUCTURE_NOT_INIT);
|
|
goto_cleanup_if_fail_with_rc_with_warning(b != NULL,
|
|
CRYPTIC_PROOF_RANGE_NO_BOUND);
|
|
|
|
cryptic_release_bn(pr->delta);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->delta = BN_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(tmp = BN_new());
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(ctx = BN_CTX_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(mont=BN_MONT_CTX_new());
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_MONT_CTX_set(mont,pr->modulus,ctx));
|
|
|
|
/*****************************
|
|
* Compute delta
|
|
******************************/
|
|
|
|
switch (rel) {
|
|
case CRYPTIC_PROOF_RANGE_LTE:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
neg = 1;
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_LT:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_sub(pr->delta,pr->delta,BN_value_one()) == 1);
|
|
neg = 1;
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_GTE:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
break;
|
|
case CRYPTIC_PROOF_RANGE_GT:
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->delta,b));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_add(pr->delta,pr->delta,BN_value_one()) == 1);
|
|
break;
|
|
default:
|
|
rc = CRYPTIC_PROOF_RANGE_RELATION_UNKNOWN;
|
|
goto cleanup;
|
|
}
|
|
|
|
goto_cleanup_if_fail_with_rc_with_warning(!BN_is_negative(pr->delta),
|
|
CRYPTIC_PROOF_RANGE_DELTA_NEGATIVE);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_TAB_DLREPS_EMPTY);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[0] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_FIRST_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[1] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_SECOND_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[2] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_THIRD_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[3] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_FORTH_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(dlreps[4] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_DLREP_DELTA_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(hash != NULL,
|
|
CRYPTIC_PROOF_GENERIC_CHALLENGE_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_TAB_RESPONSES_EMPTY);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[0] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FIRST_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[1] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FIRST_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[2] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_SECOND_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[3] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_SECOND_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[4] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_THIRD_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[5] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_THIRD_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[6] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FORTH_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[7] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_FORTH_SQRROOT_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[8] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_DELTA_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[9] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_DELTA_MISSING);
|
|
goto_cleanup_if_fail_with_rc_with_warning(responses[10] != NULL,
|
|
CRYPTIC_PROOF_RANGE_VERIFY_RESPONSES_RHO_MISSING);
|
|
|
|
pr->pokSqrRoot1 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
cryptic_check_good_rc(cryptic_zkpk_schnorr_verify_noninteractive_proof(pr->pokSqrRoot1,dlreps[0],hash,responses));
|
|
pr->pokSqrRoot2 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
cryptic_check_good_rc(cryptic_zkpk_schnorr_verify_noninteractive_proof(pr->pokSqrRoot2,dlreps[1],hash,responses+2));
|
|
pr->pokSqrRoot3 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
cryptic_check_good_rc(cryptic_zkpk_schnorr_verify_noninteractive_proof(pr->pokSqrRoot3,dlreps[2],hash,responses+4));
|
|
pr->pokSqrRoot4 = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
cryptic_check_good_rc(cryptic_zkpk_schnorr_verify_noninteractive_proof(pr->pokSqrRoot4,dlreps[3],hash,responses+6));
|
|
|
|
cryptic_release_bn(pr->dlreps[4]);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(pr->dlreps[4] = BN_new());
|
|
if(neg){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_inverse(pr->dlreps[4],dlreps[4],pr->modulus,ctx));
|
|
}else{
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->dlreps[4],dlreps[4]));
|
|
}
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->tabBases[0],pr->delta,pr->modulus,ctx,mont) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_mul(pr->dlreps[4],pr->dlreps[4],tmp,pr->modulus,ctx) == 1);
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_exp_mont(tmp,pr->dlreps[4],hash,pr->modulus,ctx,mont) == 1);
|
|
|
|
if(neg){
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(tmp,pr->tabBases[1]));
|
|
goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_mod_inverse(pr->tabBases[1],pr->tabBases[1],pr->modulus,ctx));
|
|
}
|
|
pr->pokDelta = cryptic_zkpk_schnorr_new(pr->tabBases, 2, pr->modulus);
|
|
goto_cleanup_if_fail(cryptic_zkpk_schnorr_verify_noninteractive_proof(pr->pokDelta,pr->dlreps[4],hash,responses+8) == 0);
|
|
if(neg) goto_cleanup_if_fail_with_rc_with_warning_openssl(BN_copy(pr->tabBases[1],tmp));
|
|
|
|
rc = CRYPTIC_NO_ERROR;
|
|
cleanup:
|
|
cryptic_release_ctx(ctx);
|
|
cryptic_release_mont(mont);
|
|
cryptic_release_bn(tmp);
|
|
return rc;
|
|
}
|
|
|
|
/* Getters */
|
|
BIGNUM*
|
|
cryptic_proofrange_qrg_get_modulus(CrypticProofrangeQrg *pr)
|
|
{
|
|
if(pr->modulus) {return(pr->modulus);}
|
|
else {return(NULL);}
|
|
}
|
|
|
|
BIGNUM**
|
|
cryptic_proofrange_qrg_get_dlreps(CrypticProofrangeQrg *pr)
|
|
{
|
|
if(pr->dlreps){
|
|
//concat avec delta
|
|
return(pr->dlreps);
|
|
}
|
|
else{
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
BIGNUM**
|
|
cryptic_proofrange_qrg_get_commitments(CrypticProofrangeQrg *pr)
|
|
{
|
|
if(pr->pokSqrRoot1 && pr->pokSqrRoot2 && pr->pokSqrRoot3 && pr->pokSqrRoot4 && pr->pokDelta){
|
|
int i;
|
|
for(i=0;i<6;i++){
|
|
if(!(pr->commitments[i] = BN_new())) return NULL;
|
|
}
|
|
if(!BN_copy(pr->commitments[0],cryptic_zkpk_schnorr_get_commitment(pr->pokSqrRoot1))) return NULL;
|
|
if(!BN_copy(pr->commitments[1],cryptic_zkpk_schnorr_get_commitment(pr->pokSqrRoot2))) return NULL;
|
|
if(!BN_copy(pr->commitments[2],cryptic_zkpk_schnorr_get_commitment(pr->pokSqrRoot3))) return NULL;
|
|
if(!BN_copy(pr->commitments[3],cryptic_zkpk_schnorr_get_commitment(pr->pokSqrRoot4))) return NULL;
|
|
if(!BN_copy(pr->commitments[4],cryptic_zkpk_schnorr_get_commitment(pr->pokDelta))) return NULL;
|
|
if(!BN_copy(pr->commitments[5],pr->Q)) return NULL;
|
|
return(pr->commitments);
|
|
}
|
|
else {
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
BIGNUM**
|
|
cryptic_proofrange_qrg_get_responses(CrypticProofrangeQrg *pr)
|
|
{
|
|
if(pr->pokSqrRoot1 && pr->pokSqrRoot2 && pr->pokSqrRoot3 && pr->pokSqrRoot4 && pr->pokDelta){
|
|
return(pr->responses);
|
|
}
|
|
else {
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
BIGNUM**
|
|
cryptic_proofrange_qrg_get_tabRandDLRepSqrRoot(CrypticProofrangeQrg *pr)
|
|
{
|
|
if(pr->tabRandDLRepSqrRoot){
|
|
//concat avec delta
|
|
return(pr->tabRandDLRepSqrRoot);
|
|
}
|
|
else{
|
|
return(NULL);
|
|
}
|
|
}
|