def commit(h, m, n, d): if len(h) != m * n + d + 1: raise ArithmeticError if m < 1 or n < 1 or d < 0 or d >= m: raise IndexError b = [dumb25519.random_scalar() for j in range(n)] + [dumb25519.Scalar(0)] # blinding terms M = [] # blinded coefficient matrix; initially we define using columns # the first column is unique M.append([h[i] for i in range(d)] + [h[d] - b[0]] + [dumb25519.Scalar(0) for i in range(m - d)]) # the rest of the columns (this is why there is an extra blinding term) for j in range(n): M.append([b[j]] + [h[i] for i in range(j * m + d + 1, (j + 1) * m + d)] + [h[(j + 1) * m + d] - b[j + 1]]) # test that each matrix entry is a Scalar for i in range(n + 1): for j in range(m + 1): if not isinstance(M[i][j], dumb25519.Scalar): raise TypeError # commit to each row r = [dumb25519.random_scalar() for i in range(m + 1)] # masks H = [] # commitments for i in range(m + 1): H.append(dumb25519.pedersen_commit([col[i] for col in M], r[i])) return H, [M, b, r]
def receive(private_key, account): ek = dumb25519.Scalar( int( ecies.decrypt(private_key.tsk, str(account.pk) + str(account.co), account._ek))) a = dumb25519.Scalar( int( ecies.decrypt(private_key.ssk, str(account.pk) + str(account.co), account._a))) r = dumb25519.Scalar( int( ecies.decrypt(private_key.ssk, str(account.pk) + str(account.co), account._r))) public_key = stealth.gen_public_key(private_key) s = dumb25519.hash_to_scalar( str(public_key.tpk) + str(public_key.spk) + str(ek)) if G * a + H * r != account.co: raise Exception('Bad account commitment!') if public_key.X + H * s != account.pk: raise Exception('Bad account public key!') xs = private_key.x + s return WithdrawalKey(xs, a, r, T * xs.invert())
def evaluate(state, x): if not isinstance(x, dumb25519.Scalar): raise TypeError M = state[0] r = state[2] hbar = [] n = len(M) - 1 m = len(M[0]) - 1 for j in range(n + 1): temp = dumb25519.Scalar(0) for i in range(m + 1): temp += M[j][i] * (x**i) hbar.append(temp) rbar = dumb25519.Scalar(0) for i in range(m + 1): rbar += r[i] * (x**i) return [hbar, rbar]
def prepare_witness(withdrawal_keys, deposit_keys): a_in = [withdrawal_key.a for withdrawal_key in withdrawal_keys] a_out = [deposit_key.a for deposit_key in deposit_keys] r_in = [withdrawal_key.r for withdrawal_key in withdrawal_keys] r_out = [deposit_key.r for deposit_key in deposit_keys] if len(a_in) != len(r_in) or len(a_out) != len(r_out): raise IndexError max_i = len(a_in) max_j = len(nary(R, p1)) max_k = p1 d_ijk = [] for i in range(max_i): d_ijk.append([]) i_decomp = nary(i, p1, max_j) for j in range(max_j): d_ijk[i].append([]) for k in range(max_k): if i_decomp[j] == k: d_ijk[i][j].append(dumb25519.Scalar(1)) else: d_ijk[i][j].append(dumb25519.Scalar(0)) max_i = len(a_out) max_j = len(nary(beta, p2)) a_ij = [] for i in range(max_i): a_ij.append( [dumb25519.Scalar(a) for a in nary(a_out[i].to_int(), p2, max_j)]) return Witness(d_ijk, [withdrawal_key.x for withdrawal_key in withdrawal_keys], a_in, a_ij, r_in, r_out)
def verify(proof): xG = proof.xG xH = proof.xH C_G = proof.C_G C_H = proof.C_H e0_G = proof.e0_G e0_H = proof.e0_H a0 = proof.a0 a1 = proof.a1 b0 = proof.b0 b1 = proof.b1 # generators G = dumb25519.G G1 = dumb25519.hash_to_point('G1') H = dumb448.hash_to_point('H') H1 = dumb448.hash_to_point('H1') # reconstruct hashes using commitments xG_prime = dumb25519.Z xH_prime = dumb448.Z for i in range(len(C_G)): xG_prime += dumb25519.Scalar(2)**i * C_G[i] xH_prime += dumb448.Scalar(2)**i * C_H[i] if not xG_prime == xG or not xH_prime == xH: raise ArithmeticError('Commitments do not sum to hash value!') for i in range(len(C_G)): e1_G = dumb25519.hash_to_scalar(C_G[i], C_H[i], a1[i] * G - e0_G[i] * C_G[i], b1[i] * H - e0_H[i] * C_H[i]) e1_H = dumb448.hash_to_scalar(C_G[i], C_H[i], a1[i] * G - e0_G[i] * C_G[i], b1[i] * H - e0_H[i] * C_H[i]) e0_prime_G = dumb25519.hash_to_scalar(C_G[i], C_H[i], a0[i] * G - e1_G * (C_G[i] - G1), b0[i] * H - e1_H * (C_H[i] - H1)) e0_prime_H = dumb448.hash_to_scalar(C_G[i], C_H[i], a0[i] * G - e1_G * (C_G[i] - G1), b0[i] * H - e1_H * (C_H[i] - H1)) if not e0_G[i] == e0_prime_G or not e0_H[i] == e0_prime_H: raise ArithmeticError( 'Bitwise ring signature verification failed!')
def prove(x): if not x < max_x: raise ValueError('Discrete log is too large!') if not x >= 0: raise ValueError('Discrete log must not be negative!') b = nary(x, 2) # generate blinders that sum to zero r = dumb25519.ScalarVector([]) r_sum = dumb25519.Scalar(0) s = dumb448.ScalarVector([]) s_sum = dumb448.Scalar(0) for i in range(len(b) - 1): r.append(dumb25519.random_scalar()) r_sum += dumb25519.Scalar(2)**i * r[-1] s.append(dumb448.random_scalar()) s_sum += dumb448.Scalar(2)**i * s[-1] temp_2inv_25519 = (dumb25519.Scalar(2)**(len(b) - 1)).invert() temp_2inv_448 = (dumb448.Scalar(2)**(len(b) - 1)).invert() r.append(-temp_2inv_25519 * r_sum) s.append(-temp_2inv_448 * s_sum) # sanity check on blinder sums temp_r = dumb25519.Scalar(0) temp_s = dumb448.Scalar(0) for i in range(len(b)): temp_r += dumb25519.Scalar(2)**i * r[i] temp_s += dumb448.Scalar(2)**i * s[i] if not temp_r == dumb25519.Scalar(0) or not temp_s == dumb448.Scalar(0): raise ArithmeticError('Blinder sum check failed!') # generators G = dumb25519.G G1 = dumb25519.hash_to_point('G1') H = dumb448.hash_to_point('H') H1 = dumb448.hash_to_point('H1') # commitments to bits of x C_G = dumb25519.PointVector([]) C_H = dumb448.PointVector([]) for i in range(len(b)): C_G.append(dumb25519.Scalar(b[i]) * G1 + r[i] * G) C_H.append(dumb448.Scalar(b[i]) * H1 + s[i] * H) # sanity check on commitment sums temp_C_G = dumb25519.Z temp_C_H = dumb448.Z for i in range(len(b)): temp_C_G += dumb25519.Scalar(2)**i * C_G[i] temp_C_H += dumb448.Scalar(2)**i * C_H[i] if not temp_C_G == dumb25519.Scalar( x) * G1 or not temp_C_H == dumb448.Scalar(x) * H1: raise ArithmeticError('Bit construction check failed!') # proof elements e0_G = dumb25519.ScalarVector([]) e0_H = dumb448.ScalarVector([]) a0 = dumb25519.ScalarVector([]) a1 = dumb25519.ScalarVector([]) b0 = dumb448.ScalarVector([]) b1 = dumb448.ScalarVector([]) # construct the proof for i in range(len(b)): # the current bit is 0 if b[i] == 0: j = dumb25519.random_scalar() k = dumb448.random_scalar() e1_G = dumb25519.hash_to_scalar(C_G[i], C_H[i], j * G, k * H) e1_H = dumb448.hash_to_scalar(C_G[i], C_H[i], j * G, k * H) a0.append(dumb25519.random_scalar()) b0.append(dumb448.random_scalar()) e0_G.append( dumb25519.hash_to_scalar(C_G[i], C_H[i], a0[i] * G - e1_G * (C_G[i] - G1), b0[i] * H - e1_H * (C_H[i] - H1))) e0_H.append( dumb448.hash_to_scalar(C_G[i], C_H[i], a0[i] * G - e1_G * (C_G[i] - G1), b0[i] * H - e1_H * (C_H[i] - H1))) a1.append(j + e0_G[i] * r[i]) b1.append(k + e0_H[i] * s[i]) # the current bit is 1 elif b[i] == 1: j = dumb25519.random_scalar() k = dumb448.random_scalar() e0_G.append(dumb25519.hash_to_scalar(C_G[i], C_H[i], j * G, k * H)) e0_H.append(dumb448.hash_to_scalar(C_G[i], C_H[i], j * G, k * H)) a1.append(dumb25519.random_scalar()) b1.append(dumb448.random_scalar()) e1_G = dumb25519.hash_to_scalar(C_G[i], C_H[i], a1[i] * G - e0_G[i] * C_G[i], b1[i] * H - e0_H[i] * C_H[i]) e1_H = dumb448.hash_to_scalar(C_G[i], C_H[i], a1[i] * G - e0_G[i] * C_G[i], b1[i] * H - e0_H[i] * C_H[i]) a0.append(j + e1_G * r[i]) b0.append(k + e1_H * s[i]) # somehow the bit is something else else: raise ArithmeticError('Bit decomposition must be 0 or 1!') return Proof( dumb25519.Scalar(x) * G1, dumb448.Scalar(x) * H1, C_G, C_H, e0_G, e0_H, a0, a1, b0, b1)