Example #1
0
    def __call__(self, com, g, h, a, b, x, r):
        """
        Get a conjunction of two range-power-of-two proofs.

        Args:
            com: Value of the Pedersen commitment, :math:`C = x G + r H`
            g: First commitment base point :math:`G`
            h: Second commitment base point :math:`H`
            a: Lower limit :math:`a`
            b: Upper limit :math:`b`
            x: Value for which we construct a range proof
            r: Randomizer of the commitment :math:`r`
        """
        a = ensure_bn(a)
        b = ensure_bn(b)
        num_bits = (b - a - 1).num_bits()
        offset = Bn(2)**num_bits - (b - a)

        com_shifted1 = com - a * g
        com_shifted2 = com_shifted1 + offset * g
        x1 = Secret()
        x2 = Secret()
        if x.value is not None:
            x1.value = x.value - a
            x2.value = x.value - a + offset

            # Ensure secret is in range
            if x.value < a or x.value >= b:
                warnings.warn("Secret outside of given range [{}, {})".format(
                    a, b))

        com_stmt = DLRep(com, x * g + r * h)

        p1 = PowerTwoRangeStmt(
            com=com_shifted1,
            g=g,
            h=h,
            num_bits=num_bits,
            x=x1,
            randomizer=r,
        )

        p2 = PowerTwoRangeStmt(
            com=com_shifted2,
            g=g,
            h=h,
            num_bits=num_bits,
            x=x2,
            randomizer=r,
        )

        return com_stmt & p1 & p2
Example #2
0
    def precommit(self):
        """
        Commit to the bit-decomposition of the value.
        """
        actual_value = ensure_bn(self.x.value)
        value_as_bits = decompose_into_n_bits(actual_value, self.num_bits)

        # Set true value to computed secrets
        for rand in self.randomizers:
            rand.value = self.order.random()

        precommitment = {}
        precommitment["Cs"] = [
            b * self.g + r.value * self.h
            for b, r in zip(value_as_bits, self.randomizers)
        ]

        # Compute revealed randomizer
        rand = Bn(0)
        power = Bn(1)
        for r in self.randomizers:
            rand = rand.mod_add(r.value * power, self.order)
            power *= 2
        rand = rand.mod_sub(self.randomizer.value, self.order)
        precommitment["rand"] = rand

        return precommitment
Example #3
0
    def construct_stmt(self, precommitment):
        """
        Construct the internal proof statement.
        """
        if self.is_prover:
            # Indicators that tell us which or-clause is true
            actual_value = ensure_bn(self.x.value)
            value_as_bits = decompose_into_n_bits(actual_value, self.num_bits)
            zero_simulated = [b == 1 for b in value_as_bits]
            one_simulated = [b == 0 for b in value_as_bits]

        bit_proofs = []
        for i in range(self.num_bits):
            p0 = DLRep(precommitment["Cs"][i], self.randomizers[i] * self.h)
            p1 = DLRep(precommitment["Cs"][i] - self.g,
                       self.randomizers[i] * self.h)

            # When we are a prover, mark which disjunct is true
            if self.is_prover:
                p0.set_simulated(zero_simulated[i])
                p1.set_simulated(one_simulated[i])

            bit_proofs.append(p0 | p1)

        return AndProofStmt(*bit_proofs)
Example #4
0
    def __call__(self, a, b, x=None):
        """
        Get a conjunction of two range-power-of-two proofs.
        Args:
            a: Lower limit :math:`a`
            b: Upper limit :math:`b`
            x: Value for which we construct a range proof
        """
        group = EcGroup()
        g = group.hash_to_point(b"g")
        h = group.hash_to_point(b"h")

        r = Secret(value=group.order().random())
        com = (x * g + r * h).eval()

        a = ensure_bn(a)
        b = ensure_bn(b)
        num_bits = (b - a - 1).num_bits()
        offset = Bn(2)**num_bits - (b - a)
        com_shifted1 = com - a * g
        com_shifted2 = com_shifted1 + offset * g

        x1 = Secret()
        x2 = Secret()
        if x is not None:
            x1.value = x.value - a
            x2.value = x.value - a + offset

        com_stmt = DLRep(com, x * g + r * h)
        p1 = PowerTwoRangeStmt(
            com=com_shifted1,
            g=g,
            h=h,
            num_bits=num_bits,
            x=x1,
            randomizer=r,
        )
        p2 = PowerTwoRangeStmt(
            com=com_shifted2,
            g=g,
            h=h,
            num_bits=num_bits,
            x=x2,
            randomizer=r,
        )

        return com_stmt & p1 & p2
Example #5
0
    def __init__(self, com, g, h, num_bits, x=None, randomizer=None):
        if not x.value is None and not randomizer.value is None:
            self.x = x
            self.randomizer = randomizer
            self.is_prover = True

            # Ensure secret is in range
            self.x.value = ensure_bn(self.x.value)
            if self.x.value < 0:
                warnings.warn("Secret is negative")
            if self.x.value.num_bits() > num_bits:
                warnings.warn("Secret has more than {} bits".format(num_bits))
        else:
            self.is_prover = False

        # TODO: Should we combine com with the inner proof?
        self.com = com
        self.g = g
        self.h = h
        self.order = g.group.order()
        self.num_bits = num_bits

        # The constructed proofs need extra randomizers as secrets
        self.randomizers = [Secret() for _ in range(self.num_bits)]