예제 #1
0
def sender_payee_address_from_stealth(sender_prikey, receiver_pubkey):
    # sender - derive payee address
    ss1 = btc.multiply(receiver_pubkey, sender_prikey)
    ss2 = btc.sha256(btc.encode_pubkey((ss1), 'bin_compressed'))
    addr = btc.pubkey_to_address(btc.add_pubkeys(
        receiver_pubkey, btc.privtopub(ss2)))
    return addr
예제 #2
0
    def get_commitment(self) -> Point:
        """
        Returns:

        c * U + v_1 * G_1 + v_2 * G_2 + ... + v_n * G_n +
        w_1 * H_1 + w_2 * H_2 + ... + w_n + H_n
        """
        P = B.multiply(self.U, self.c)

        for g_x, a_x in zip(self.G, self.a):
            P = B.add_pubkeys(P, B.fast_multiply(g_x, a_x))

        for h_x, b_x in zip(self.H, self.b):
            P = B.add_pubkeys(P, B.fast_multiply(h_x, b_x))

        return P
예제 #3
0
    def get_proof_recursive(
            self, a: Vector, b: Vector, P: Point, G: List[Point],
            H: List[Point],
            N: int) -> Tuple[Scalar, Scalar, List[Point], List[Point]]:
        # Can't compress L and R no more
        if N == 1:
            # Return tuple a', b', L[], R[]
            # total size is 2 * scalar_size * log(n) * 2 * point_size
            return (a[0], b[0], self.L, self.R)

        aL, aR = split(a)
        bL, bR = split(b)
        gL, gR = split(G)
        hL, hR = split(H)

        self.L.append(
            InnerProductCommitment(aL, bR, G=gR, H=hL,
                                   U=self.U).get_commitment())
        self.R.append(
            InnerProductCommitment(aR, bL, G=gL, H=hR,
                                   U=self.U).get_commitment())

        (self.fs_state, _) = fiat_shamir(self.fs_state,
                                         [self.L[-1], self.R[-1], P],
                                         nret=0)
        (x, x_sq, xinv, x_sq_inv) = bytes_to_xes(self.fs_state)

        # Construct change of coordinates for base points, and for vector terms
        gprime = []
        hprime = []
        aprime = []
        bprime = []

        for i in range(int(N / 2)):
            gprime.append(
                B.add_pubkeys(B.multiply(G[i], xinv),
                              B.multiply(G[i + int(N / 2)], x)))

            hprime.append(
                B.add_pubkeys(B.multiply(H[i], x),
                              B.multiply(H[i + int(N / 2)], xinv)))

            aprime.append(x * a[i] + xinv * a[i + int(N / 2)] % B.N)

            bprime.append((xinv * b[i]) + x * b[i + int(N / 2)] % B.N)

        p_prime = B.add_pubkeys(P, B.multiply(self.L[-1], x_sq))
        p_prime = B.add(p_prime, B.multiply(self.R[-1], x_sq_inv))

        return self.get_proof_recursive(Vector(aprime), Vector(bprime),
                                        p_prime, gprime, hprime, int(N / 2))
예제 #4
0
    def verify_proof_recursive(self, P: Point, L: Point, R: Point, a: Scalar,
                               b: Scalar, G: List[Point], H: List[Point],
                               N: int):
        if N == 1:
            p_prime = InnerProductCommitment(Vector([a]),
                                             Vector([b]),
                                             G=G,
                                             H=H,
                                             U=self.U).get_commitment()

            return P == p_prime

        (self.fs_state,
         _) = fiat_shamir(self.fs_state,
                          [L[self.verify_iter], R[self.verify_iter], P],
                          nret=0)
        (x, x_sq, xinv, x_sq_inv) = bytes_to_xes(self.fs_state)

        gprime = []
        hprime = []

        for i in range((int(N / 2))):
            gprime.append(
                B.add_pubkeys(B.multiply(G[i], xinv),
                              B.multiply(G[i + int(N / 2)], x)))

            hprime.append(
                B.add_pubkeys(B.multiply(H[i], x),
                              B.multiply(H[i + int(N / 2)], xinv)))

        p_prime1 = B.add_pubkeys(P, B.multiply(L[self.verify_iter], x_sq))
        p_prime = B.add_pubkeys(p_prime1,
                                B.multiply(R[self.verify_iter], x_sq_inv))

        self.verify_iter = self.verify_iter + 1

        return self.verify_proof_recursive(p_prime, L, R, a, b, gprime, hprime,
                                           int(N / 2))
예제 #5
0
    def generate_proof(self, value: Scalar):
        """
        Given a value, follow the algorithm laid out
        on p.16, 17 (section 4.2) of paper for prover side
        """
        fs_state = b''

        # Vector of all 1's or 0's
        # Mainly for readability
        zeros = Vector([0] * self.bitlength)
        ones = Vector([1] * self.bitlength)
        twos = Vector([2] * self.bitlength)
        power_of_twos = to_powervector(2, self.bitlength)

        aL = to_bitvector(value, self.bitlength)
        aR = aL - ones

        assert aL * aR == zeros
        assert aL @ power_of_twos == value

        # Pederson Commitment to fulfill the hiding and binding properties
        # of bulletproof. Binding value is automatically created
        gamma = get_blinding_value()
        pc = PedersonCommitment(value, b=gamma)
        V: Point = pc.get_commitment()

        alpha: Scalar = get_blinding_value()
        A = InnerProductCommitment(aL, aR, c=alpha, U=getNUMS(255))
        P_a: Point = A.get_commitment()

        sL = get_blinding_vector(self.bitlength)
        sR = get_blinding_vector(self.bitlength)
        rho = get_blinding_value()

        S = InnerProductCommitment(sL, sR, c=rho, U=getNUMS(255))
        P_s: Point = S.get_commitment()

        fs_state, fs_challanges = fiat_shamir(fs_state, [V, P_a, P_s])
        y: Point = fs_challanges[0]
        z: Point = fs_challanges[1]

        z2 = pow(z, 2, B.N)
        zv = Vector([z] * self.bitlength)

        # Construct l(x) and r(x) coefficients;
        # l[0] = constant term
        # l[1] = linear term
        # same for r(x)
        l: List[Vector] = [aL - zv, sL]
        yn: Vector = to_powervector(y, self.bitlength)

        # 0th coeff is y^n ⋅ (aR + z ⋅ 1^n) + (z^2 ⋅ 2^n)
        # operators have been overloaded, so all good
        r: List[Vector] = [
            # operator overloading works if vector is first
            (yn * (aR + zv)) + (power_of_twos * z2),
            yn * sR
        ]

        # Constant term of t(x) = <l(x), r(x)> is the inner product
        # of the constant terms of l(x)and r(x)
        t0: Scalar = l[0] @ r[0]
        t2: Scalar = l[1] @ r[1]
        t1: Scalar = (((l[0] + l[1]) @ (r[0] + r[1])) - t0 - t2) % B.N

        tau1 = get_blinding_value()
        T1 = PedersonCommitment(t1, b=tau1)

        tau2 = get_blinding_value()
        T2 = PedersonCommitment(t2, b=tau2)

        fs_state, fs_challanges = fiat_shamir(
            fs_state,
            [T1.get_commitment(), T2.get_commitment()], nret=1)
        x_1: Scalar = fs_challanges[0]
        mu = (alpha + rho * x_1) % B.N
        tau_x = (z2 * gamma + tau1 * x_1 + tau2 * x_1 * x_1) % B.N

        # lx and rx are vetor-value first degree polynomials evaluated at
        # the challenge value x_1
        lx: Vector = l[0] + (l[1] * x_1)
        rx: Vector = r[0] + (r[1] * x_1)
        t: Scalar = (t0 + t1 * x_1 + t2 * x_1 * x_1) % B.N

        assert t == lx @ rx

        # Prover can new send tau_x, mu and t to verifier
        # inner product argument can be verified from this data
        hprime = []
        yinv = modinv(y, B.N)

        for i in range(self.bitlength):
            hprime.append(B.multiply(A.H[i], pow(yinv, i, B.N)))

        fs_state, fs_challanges = fiat_shamir(fs_state, [tau_x, mu, t], nret=1)
        uchallenge = fs_challanges[0]

        U = B.multiply(B.G, uchallenge)

        # On the prover side, need to construct an inner product argument
        iproof = InnerProductCommitment(lx, rx, U=U, H=hprime)
        proof = iproof.generate_proof()

        ak: Scalar = proof[0]
        bk: Scalar = proof[1]
        lk: List[Point] = proof[2]
        rk: List[Point] = proof[3]

        # At this point we have a valid data set, but here is included a
        # sanity check that the inner product proof we've generated actually verifies
        iproof2 = InnerProductCommitment(ones, twos, H=hprime, U=U)

        assert iproof2.verify_proof(ak, bk, iproof.get_commitment(), lk, rk)

        self.proof = proof
        self.tau_x = tau_x
        self.gamma = gamma
        self.mu = mu
        self.T1 = T1
        self.T2 = T2
        self.A = A
        self.S = S
        self.t = t
        self.V = V
예제 #6
0
    def verify(self, Ap, Sp, T1p, T2p, tau_x, mu, t, proof, V):
        fs_state = b''

        # Compute challenges to find x, y, z
        fs_state, fs_challenge = fiat_shamir(fs_state, [V, Ap, Sp])
        y: Scalar = fs_challenge[0]
        z: Scalar = fs_challenge[1]
        z2 = pow(z, 2, B.N)

        fs_state, fs_challenge = fiat_shamir(fs_state, [T1p, T2p], nret=1)
        x_1 = fs_challenge[0]

        # Construct verification equation (61)
        power_of_ones = to_powervector(1, self.bitlength)
        power_of_twos = to_powervector(2, self.bitlength)
        yn = to_powervector(y, self.bitlength)

        k: Scalar = ((yn @ power_of_ones) * (-z2)) % B.N
        k = (k - (power_of_ones @ power_of_twos) * pow(z, 3, B.N)) % B.N

        gexp: Scalar = (k + z * (power_of_ones @ yn)) % B.N

        lhs = PedersonCommitment(t, b=tau_x).get_commitment()

        rhs = B.multiply(B.G, gexp)
        rhs = B.add_pubkeys(rhs, B.multiply(V, z2))
        rhs = B.add_pubkeys(rhs, B.multiply(T1p, x_1))
        rhs = B.add_pubkeys(rhs, B.multiply(T2p, pow(x_1, 2, B.N)))

        if not lhs == rhs:
            print('(61) verification check failed')
            return False

        # HPrime
        hprime = []
        yinv = modinv(y, B.N)

        for i in range(1, self.bitlength + 1):
            hprime.append(
                B.multiply(getNUMS(self.bitlength + i), pow(yinv, i - 1, B.N)))

        # Reconstruct P
        P = B.add_pubkeys(B.multiply(Sp, x_1), Ap)

        # Add g*^(-z)
        for i in range(self.bitlength):
            P = B.add_pubkeys(B.multiply(getNUMS(i + 1), -z % B.N), P)

        # zynz22n is the exponent of hprime
        zynz22n = (yn * z) + (power_of_twos * z2)

        for i in range(self.bitlength):
            P = B.add_pubkeys(B.multiply(hprime[i], zynz22n[i]), P)

        fs_state, fs_challenge = fiat_shamir(fs_state, [tau_x, mu, t], nret=1)
        uchallenge: Scalar = fs_challenge[0]
        U = B.multiply(B.G, uchallenge)
        P = B.add_pubkeys(B.multiply(U, t), P)

        # P should now be : A + xS + -zG* + (zy^n+z^2.2^n)H'* + tU
        # One can show algebraically (the working is omitted from the paper)
        # that this will be the same as an inner product commitment to
        # (lx, rx) vectors (whose inner product is t), thus the variable 'proof'
        # can be passed into the IPC verify call, which should pass.
        # input to inner product proof is P.h^-(mu)
        p_prime = B.add_pubkeys(P, B.multiply(getNUMS(255), -mu % B.N))

        a, b, L, R = proof

        iproof = InnerProductCommitment(power_of_ones,
                                        power_of_twos,
                                        H=hprime,
                                        U=U)

        return iproof.verify_proof(a, b, p_prime, L, R)
예제 #7
0
def receiver_payee_privkey_from_stealth(receiver_prikey, sender_pubkey):
    # sender - derive payee address
    ss1 = btc.multiply(sender_pubkey, receiver_prikey)
    ss2 = btc.sha256(btc.encode_pubkey((ss1), 'bin_compressed'))
    key = btc.add_privkeys(receiver_prikey, ss2)
    return key
예제 #8
0
H = getNUMS(255)
N = 4

# P -> V: C_0
r = get_blinding_vector(N)
x = get_blinding_vector(N)

commitments = [
    PedersonCommitment(x[i], b=r[i]).get_commitment() for i in range(N)
]

# V -> P: e
e = get_blinding_value()
ev = to_powervector(e, N)

# P -> V (z, s)

# P
P = commitments[0]
for i in range(1, N):
    P = B.add_pubkeys(B.multiply(commitments[i], ev[i]), P)

z = ev * x
s = ev @ r

V = B.multiply(H, s)
for i in range(N):
    V = B.add_pubkeys(B.multiply(B.G, z[i]), V)

assert V == P
예제 #9
0
    def get_commitment(self) -> Point:
        Hb = B.multiply(self.h, self.b)
        Gv = B.multiply(self.g, self.v)

        return B.add(Hb, Gv)