def batch_delete_using_membership_proofs(A_pre_delete, S, x_list, proofs_list, n, agg_indexes=[]): is_aggregated = len(agg_indexes) > 0 if is_aggregated and len(proofs_list) != len(agg_indexes): return None if (not is_aggregated) and len(x_list) != len(proofs_list): return None members = [] if is_aggregated: # sanity - verify each and every proof individually for i, indexes in enumerate(agg_indexes): current_x_list = x_list[indexes[0]: indexes[1]] current_nonce_list = [S[x] for x in current_x_list] product = __calculate_primes_product(current_x_list, current_nonce_list) members.append(product) for x in current_x_list: del S[x] else: for x in x_list: members.append(hash_to_prime(x, ACCUMULATED_PRIME_SIZE, S[x])[0]) del S[x] A_post_delete = proofs_list[0] product = members[0] for i in range(len(members))[1:]: A_post_delete = shamir_trick(A_post_delete, proofs_list[i], product, members[i], n) product *= members[i] return A_post_delete, prove_exponentiation(A_post_delete, product, A_pre_delete, n)
def __calculate_primes_product(x_list, nonce_list): if len(x_list) != len(nonce_list): return None primes_list = [hash_to_prime(x, nonce=nonce_list[i])[0] for i, x in enumerate(x_list)] product = calculate_product(primes_list) return product
def prove_non_membership(A0, S, x, x_nonce, n): if x in S.keys(): return None else: product = 1 for element in S.keys(): nonce = S[element] product *= hash_to_prime(element, ACCUMULATED_PRIME_SIZE, nonce)[0] prime = hash_to_prime(x, ACCUMULATED_PRIME_SIZE, x_nonce)[0] a, b = bezoute_coefficients(prime, product) if a < 0: positive_a = -a inverse_A0 = mul_inv(A0, n) d = pow(inverse_A0, positive_a, n) else: d = pow(A0, a, n) return d, b
def batch_prove_membership(A0, S, x_list, n): product = 1 for element in S.keys(): if element not in x_list: nonce = S[element] product *= hash_to_prime(element, ACCUMULATED_PRIME_SIZE, nonce)[0] A = pow(A0, product, n) return A
def add(A, S, x, n): if x in S.keys(): return A else: hash_prime, nonce = hash_to_prime(x, ACCUMULATED_PRIME_SIZE) A = pow(A, hash_prime, n) S[x] = nonce return A
def verify_non_membership(A0, A_final, d, b, x, x_nonce, n): prime = hash_to_prime(x, ACCUMULATED_PRIME_SIZE, x_nonce)[0] if b < 0: positive_b = -b inverse_A_final = mul_inv(A_final, n) second_power = pow(inverse_A_final, positive_b, n) else: second_power = pow(A_final, b, n) return (pow(d, prime, n) * second_power) % n == A0
def test_shamir_trick_2(self): n, A0, S = setup() elements_list = create_list(2) A1 = add(A0, S, elements_list[0], n) A2 = add(A1, S, elements_list[1], n) prime0 = hash_to_prime(elements_list[0], nonce=S[elements_list[0]])[0] prime1 = hash_to_prime(elements_list[1], nonce=S[elements_list[1]])[0] proof0 = prove_membership(A0, S, elements_list[0], n) proof1 = prove_membership(A0, S, elements_list[1], n) agg_proof = shamir_trick(proof0, proof1, prime0, prime1, n) is_valid = pow(agg_proof, prime0 * prime1, n) == A2 self.assertTrue(is_valid)
def batch_add(A_pre_add, S, x_list, n): product = 1 for x in x_list: if x not in S.keys(): hash_prime, nonce = hash_to_prime(x, ACCUMULATED_PRIME_SIZE) S[x] = nonce product *= hash_prime A_post_add = pow(A_pre_add, product, n) return A_post_add, prove_exponentiation(A_pre_add, product, A_post_add, n)
def delete(A0, A, S, x, n): if x not in S.keys(): return A else: del S[x] product = 1 for element in S.keys(): nonce = S[element] product *= hash_to_prime(element, ACCUMULATED_PRIME_SIZE, nonce)[0] Anew = pow(A0, product, n) return Anew
def test_batch_add(self): n, A0, S = setup() elements_list = create_list(10) A_post_add, nipoe = batch_add(A0, S, elements_list, n) self.assertEqual(len(S), 10) nonces_list = list(map(lambda e: hash_to_prime(e)[1], elements_list)) is_valid = batch_verify_membership_with_NIPoE(nipoe[0], nipoe[1], A0, elements_list, nonces_list, A_post_add, n) self.assertTrue(is_valid)
def prove_membership(A0, S, x, n): if x not in S.keys(): return None else: product = 1 for element in S.keys(): if element != x: nonce = S[element] product *= hash_to_prime(element, ACCUMULATED_PRIME_SIZE, nonce)[0] A = pow(A0, product, n) return A
def aggregate_membership_witnesses(A, witnesses_list, x_list, nonces_list, n): primes = [] for i in range(len(x_list)): prime = hash_to_prime(x_list[i], ACCUMULATED_PRIME_SIZE, nonces_list[i])[0] primes.append(prime) agg_wit = witnesses_list[0] product = primes[0] for i in range(len(x_list))[1:]: agg_wit = shamir_trick(agg_wit, witnesses_list[i], product, primes[i], n) product *= primes[i] return agg_wit, prove_exponentiation(agg_wit, product, A, n)
def test_batch_proof_of_membership_with_NIPoE(self): n, A0, S = setup() elements_list = create_list(10) A = A0 for x in elements_list: A = add(A, S, x, n) A_final = A elements_to_prove_list = [elements_list[4], elements_list[7], elements_list[8]] Q, l_nonce, u = batch_prove_membership_with_NIPoE(A0, S, elements_to_prove_list, n, A_final) nonces_list = list(map(lambda e: hash_to_prime(e)[1], elements_to_prove_list)) is_valid = batch_verify_membership_with_NIPoE(Q, l_nonce, u, elements_to_prove_list, nonces_list, A_final, n) self.assertTrue(is_valid)
def test_batch_proof_of_membership(self): n, A0, S = setup() elements_list = create_list(10) A = A0 for x in elements_list: A = add(A, S, x, n) A_final = A elements_to_prove_list = [elements_list[4], elements_list[7], elements_list[8]] A_intermediate = batch_prove_membership(A0, S, elements_to_prove_list, n=n) nonces_list = list(map(lambda e: hash_to_prime(e)[1], elements_to_prove_list)) is_valid = batch_verify_membership(A_final, elements_to_prove_list, nonces_list, A_intermediate, n) self.assertTrue(is_valid)
def test_prove_non_membership(self): n, A0, S = setup() elements_list = create_list(3) A1 = add(A0, S, elements_list[0], n) A2 = add(A1, S, elements_list[1], n) A3 = add(A2, S, elements_list[2], n) proof = prove_non_membership(A0, S, elements_list[0], S[elements_list[0]], n) self.assertIsNone(proof) x = create_list(1)[0] prime, x_nonce = hash_to_prime(x) proof = prove_non_membership(A0, S, x, x_nonce, n) is_valid = verify_non_membership(A0, A3, proof[0], proof[1], x, x_nonce, n) self.assertTrue(is_valid)
def test_batch_delete(self): n, A0, S = setup() elements_list = create_list(5) A = A0 for i in range(len(elements_list)): A = add(A, S, elements_list[i], n) A_pre_delete = A elements_to_delete_list = [elements_list[0], elements_list[2], elements_list[4]] nonces_list = list(map(lambda e: hash_to_prime(e)[1], elements_to_delete_list)) proofs = list(map(lambda x: prove_membership(A0, S, x, n), elements_to_delete_list)) A_post_delete, nipoe = batch_delete_using_membership_proofs(A_pre_delete, S, elements_to_delete_list, proofs, n) is_valid = batch_verify_membership_with_NIPoE(nipoe[0], nipoe[1], A_post_delete, elements_to_delete_list, nonces_list, A_pre_delete, n) self.assertTrue(is_valid)
def prove_membership_with_NIPoE(g, S, x, n, w): u = prove_membership(g, S, x, n) x_prime, x_nonce = hash_to_prime(x=x, nonce=S[x]) (Q, l_nonce) = prove_exponentiation(u, x_prime, w, n) return Q, l_nonce, u
def verify_exponentiation(Q, l_nonce, u, x, x_nonce, w, n): x = hash_to_prime(x=x, nonce=x_nonce)[0] return __verify_exponentiation(Q, l_nonce, u, x, w, n)
def test_hash_to_prime(self): x = secrets.randbelow(pow(2, 256)) h, nonce = hash_to_prime(x, 128) self.assertTrue(is_prime(h)) self.assertTrue(h, math.log2(h) < 128)
def __verify_exponentiation(Q, l_nonce, u, x, w, n): l = hash_to_prime(x=(concat(x, u, w)), nonce=l_nonce)[0] r = x % l # check (Q^l)(u^r) == w return (pow(Q, l, n) % n) * (pow(u, r, n) % n) % n == w
def verify_membership(A, x, nonce, proof, n): return __verify_membership(A, hash_to_prime(x=x, num_of_bits=ACCUMULATED_PRIME_SIZE, nonce=nonce)[0], proof, n)
def create_all_membership_witnesses(A0, S, n): primes = [hash_to_prime(x=x, nonce=S[x])[0] for x in S.keys()] return root_factor(A0, primes, n)
def prove_exponentiation(u, x, w, n): l, nonce = hash_to_prime(concat(x, u, w)) # Fiat-Shamir instead of interactive challenge q = x // l Q = pow(u, q, n) return Q, nonce