예제 #1
0
bool CommitmentProofOfKnowledge::Verify(const Bignum& A, const Bignum& B) const
{
    // TODO: First verify that the values
    // S1, S2 and S3 and "challenge" are in the correct ranges
    if((this->challenge < Bignum(0)) || (this->challenge > (Bignum(2).pow(256) - Bignum(1)))){
        return false;
    }
    
    // Compute T1 = g1^S1 * h1^S2 * inverse(A^{challenge}) mod p1
    Bignum T1 = A.pow_mod(this->challenge, ap->modulus).inverse(ap->modulus).mul_mod(
                                                                         (ap->g.pow_mod(S1, ap->modulus).mul_mod(ap->h.pow_mod(S2, ap->modulus), ap->modulus)),
                                                                         ap->modulus);
    
    // Compute T2 = g2^S1 * h2^S3 * inverse(B^{challenge}) mod p2
    Bignum T2 = B.pow_mod(this->challenge, bp->modulus).inverse(bp->modulus).mul_mod(
                                                                         (bp->g.pow_mod(S1, bp->modulus).mul_mod(bp->h.pow_mod(S3, bp->modulus), bp->modulus)),
                                                                         bp->modulus);
    
    // Hash T1 and T2 along with all of the public parameters
    Bignum computedChallenge = calculateChallenge(A, B, T1, T2);
    
    // Return success if the computed challenge matches the incoming challenge
    if(computedChallenge == this->challenge){
        return true;
    }
    
    // Otherwise return failure
    return false;
}
예제 #2
0
// TODO: get parameters from the commitment group
CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* aParams,
        const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b):
	ap(aParams),bp(bParams)
{
	CBigNum r1, r2, r3;

	// First: make sure that the two commitments have the
	// same contents.
	if (a.getContents() != b.getContents()) {
		throw std::runtime_error("Both commitments must contain the same value");
	}

	// Select three random values "r1, r2, r3" in the range 0 to (2^l)-1 where l is:
	// length of challenge value + max(modulus 1, modulus 2, order 1, order 2) + margin.
	// We set "margin" to be a relatively generous  security parameter.
	//
	// We choose these large values to ensure statistical zero knowledge.
	uint32_t randomSize = COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN +
	                      std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()),
	                               std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize()));
	CBigNum maxRange = (CBigNum(2).pow(randomSize) - CBigNum(1));

	r1 = CBigNum::randBignum(maxRange);
	r2 = CBigNum::randBignum(maxRange);
	r3 = CBigNum::randBignum(maxRange);

	// Generate two random, ephemeral commitments "T1, T2"
	// of the form:
	// T1 = g1^r1 * h1^r2 mod p1
	// T2 = g2^r1 * h2^r3 mod p2
	//
	// Where (g1, h1, p1) are from "aParams" and (g2, h2, p2) are from "bParams".
	CBigNum T1 = this->ap->g.pow_mod(r1, this->ap->modulus).mul_mod((this->ap->h.pow_mod(r2, this->ap->modulus)), this->ap->modulus);
	CBigNum T2 = this->bp->g.pow_mod(r1, this->bp->modulus).mul_mod((this->bp->h.pow_mod(r3, this->bp->modulus)), this->bp->modulus);

	// Now hash commitment "A" with commitment "B" as well as the
	// parameters and the two ephemeral commitments "T1, T2" we just generated
	this->challenge = calculateChallenge(a.getCommitmentValue(), b.getCommitmentValue(), T1, T2);

	// Let "m" be the contents of the commitments "A, B". We have:
	// A =  g1^m  * h1^x  mod p1
	// B =  g2^m  * h2^y  mod p2
	// T1 = g1^r1 * h1^r2 mod p1
	// T2 = g2^r1 * h2^r3 mod p2
	//
	// Now compute:
	//  S1 = r1 + (m * challenge)   -- note, not modular arithmetic
	//  S2 = r2 + (x * challenge)   -- note, not modular arithmetic
	//  S3 = r3 + (y * challenge)   -- note, not modular arithmetic
	this->S1 = r1 + (a.getContents() * this->challenge);
	this->S2 = r2 + (a.getRandomness() * this->challenge);
	this->S3 = r3 + (b.getRandomness() * this->challenge);

	// We're done. The proof is S1, S2, S3 and "challenge", all of which
	// are stored in member variables.
}
예제 #3
0
// TODO: get parameters from the commitment group
CommitmentProofOfKnowledge::CommitmentProofOfKnowledge(const IntegerGroupParams* aParams,
        const IntegerGroupParams* bParams, const Commitment& a, const Commitment& b):
        ap(aParams),bp(bParams) {
    Bignum r1;
    
    // First: make sure that the two commitments have the
    // same contents.
    if(a.getContents() != b.getContents()){
        throw std::invalid_argument("Both commitments must contain the same value");
    }
    
    // In order to ensure statistical zero knowledge, we pick "r1" out of the
    // largest possible range. In this case, the smaller of the two group orders.
    if(this->ap->groupOrder < this->bp->groupOrder){
        r1 = Bignum::randBignum(ap->groupOrder);
    }else{
        r1 = Bignum::randBignum(bp->groupOrder);
    }
    
    // Generate two random, ephemeral commitments "T1, T2" to "r1" under the two different
    // sets of commitment parameters.
    Commitment t1(aParams, r1);
    Commitment t2(bParams, r1);
    Bignum T1 = t1.getCommitmentValue();
    Bignum T2 = t2.getCommitmentValue();
    
    // Now hash commitment "A" with commitment "B" as well as the
    // parameters and the two ephemeral commitments "T1, T2" we just generated
    this->challenge = calculateChallenge(a.getCommitmentValue(), b.getCommitmentValue(), T1, T2);
    
    // Let "m" be the contents of the commitments. We'll implicitly define
    // A =  g1^m  * h1^x  mod p1
    // B =  g2^m  * h2^y  mod p2
    // T1 = g1^r1 * h1^r2 mod p1
    // T2 = g2^r1 * h2^r3 mod p2
    //
    // Now compute:
    //  S1 = r1 + (m * challenge)
    //  S2 = r2 + (x * challenge)
    //  S3 = r3 + (y * challenge)
    S1 = t1.getContents() + (a.getContents() * challenge);
    S2 = t1.getRandomness() + (a.getRandomness() * challenge);
    S3 = t2.getRandomness() + (b.getRandomness() * challenge);
    
    // We're done. The proof is S1, S2, S3 and "challenge".
}
예제 #4
0
bool CommitmentProofOfKnowledge::Verify(const CBigNum& A, const CBigNum& B) const
{
	// Compute the maximum range of S1, S2, S3 and verify that the given values are
	// in a correct range. This might be an unnecessary check.
	uint32_t maxSize = 64 * (COMMITMENT_EQUALITY_CHALLENGE_SIZE + COMMITMENT_EQUALITY_SECMARGIN +
	                         std::max(std::max(this->ap->modulus.bitSize(), this->bp->modulus.bitSize()),
	                                  std::max(this->ap->groupOrder.bitSize(), this->bp->groupOrder.bitSize())));

	if ((uint32_t)this->S1.bitSize() > maxSize ||
	        (uint32_t)this->S2.bitSize() > maxSize ||
	        (uint32_t)this->S3.bitSize() > maxSize ||
	        this->S1 < CBigNum(0) ||
	        this->S2 < CBigNum(0) ||
	        this->S3 < CBigNum(0) ||
	        this->challenge < CBigNum(0) ||
	        this->challenge > (CBigNum(2).pow(COMMITMENT_EQUALITY_CHALLENGE_SIZE) - CBigNum(1))) {
		// Invalid inputs. Reject.
		return false;
	}

	// Compute T1 = g1^S1 * h1^S2 * inverse(A^{challenge}) mod p1
	CBigNum T1 = A.pow_mod(this->challenge, ap->modulus).inverse(ap->modulus).mul_mod(
	                (ap->g.pow_mod(S1, ap->modulus).mul_mod(ap->h.pow_mod(S2, ap->modulus), ap->modulus)),
	                ap->modulus);

	// Compute T2 = g2^S1 * h2^S3 * inverse(B^{challenge}) mod p2
	CBigNum T2 = B.pow_mod(this->challenge, bp->modulus).inverse(bp->modulus).mul_mod(
	                (bp->g.pow_mod(S1, bp->modulus).mul_mod(bp->h.pow_mod(S3, bp->modulus), bp->modulus)),
	                bp->modulus);

	// Hash T1 and T2 along with all of the public parameters
	CBigNum computedChallenge = calculateChallenge(A, B, T1, T2);

	// Return success if the computed challenge matches the incoming challenge
	return computedChallenge == this->challenge;
}