def add_reading(inputs, reference_inputs, parameters, meter_priv, reading, opening): # compute output old_meter = loads(inputs[0]) new_meter = loads(inputs[0]) # create commitement to the reading (G, g, (h0, _, _, _), _) = setup() commitment = loads(reading) * g + unpack(opening) * h0 # update readings new_meter['readings'].append(pack(commitment)) # hash message to sign hasher = sha256() hasher.update(dumps(old_meter).encode('utf8')) hasher.update(dumps(pack(commitment)).encode('utf8')) # sign message sig = do_ecdsa_sign(G, unpack(meter_priv), hasher.digest()) # return return { 'outputs': (dumps(new_meter), ), 'extra_parameters': { 'reading': pack(commitment), 'signature': pack(sig) } }
def create_petition_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: # retrieve petition petition = loads(outputs[1]) num_options = len(petition['options']) print "CHECKING (create) - check format" if len(inputs) != 1 or len(reference_inputs) != 0 or len( outputs) != 2 or len(returns) != 0: return False if num_options < 1 or num_options != len(petition['scores']): return False print "CHECKING (create) - check tokens" if loads(inputs[0])['type'] != 'PetitionEncToken' or loads( outputs[0])['type'] != 'PetitionEncToken': return False if petition['type'] != 'PetitionEncObject': return False print "CHECKING (create) - check proof" params = setup() proof_init = unpack(parameters[0]) tally_pub = unpack(petition['tally_pub']) for value in petition['scores']: if not verifyzero(params, tally_pub, unpack(value), proof_init): return False # otherwise return True except (KeyError, Exception): return False
def create_vote(inputs, reference_inputs, parameters, options, participants, tally_priv, tally_pub): # genrate param params = setup() pub = unpack(tally_pub) # encrypt initial score (a, b, k) = binencrypt(params, pub, 0) # encryption of a zero c = (a, b) scores = [pack(c) for _ in loads(options)] # new vote object new_vote = { 'type': 'VoteObject', 'options': loads(options), 'scores': scores, 'participants': loads(participants), 'tally_pub': tally_pub } # proof that all init values are zero proof_init = provezero(params, pub, c, unpack(tally_priv)) # return return { 'outputs': (inputs[0], dumps(new_vote)), 'extra_parameters': { 'proof_init': pack(proof_init) } }
def validate_sig(sig, pub, msg="proof"): # check that the signature on the proof is correct hasher = sha256() hasher.update(msg) # verify signature (G, _, _, _) = setup() if not do_ecdsa_verify(G, unpack(pub), unpack(sig), hasher.digest()): raise Exception("Invalid signature")
def transfer_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: amount = loads(parameters[0]) input_from_account = loads(inputs[0]) input_to_account = loads(inputs[1]) output_from_account = loads(outputs[0]) output_to_account = loads(outputs[1]) # check format if len(inputs) != 2 or len(reference_inputs) != 0 or len(outputs) != 2 or len(returns) != 0: return False if input_from_account['pub'] != output_from_account['pub'] or input_to_account['pub'] != output_to_account['pub']: return False # check tokens if input_from_account['type'] != 'BankAccount' or input_to_account['type'] != 'BankAccount': return False if output_from_account['type'] != 'BankAccount' or output_to_account['type'] != 'BankAccount': return False # amount transfered should be non-negative if amount < 0: return False # amount transfered should not exceed balance if input_from_account['balance'] < amount: return False # consistency between inputs and outputs if input_from_account['balance'] != output_from_account['balance'] + amount: return False if input_to_account['balance'] != output_to_account['balance'] - amount: return False # verify transaction if input_from_account['callback'] == None: sig = unpack(parameters[1]) pub = unpack(input_from_account['pub']) hasher = sha256() hasher.update(dumps(inputs).encode('utf8')) hasher.update(dumps(parameters[0]).encode('utf8')) G = setup()[0] if not do_ecdsa_verify(G, pub, sig, hasher.digest()): return False else: # verify depend transaction -- specified by 'callback' # NOTE: the checker of the dependency is automatcally called callback = dependencies[0] if callback['contractID']+'.'+callback['methodID'] != input_from_account['callback']: return False # NOTE: this is not enough -- this only verifes that a particular process has been called, # we also need to verify the inputs of that process: e.g., verifying that a bank transfer has been done # is useless if you don't verify the beneficiary. Any idea ? # otherwise return True except (KeyError, Exception): return False
def add_signature(inputs, reference_inputs, parameters, added_signature): old_signature = loads(inputs[0]) new_signature = loads(inputs[0]) added_signature = loads(added_signature) params = setup() tally_pub = unpack(old_signature['tally_pub']) # encrypt signatures & proofs to build enc_added_signatures = [] # encrypted signatures proof_bin = [ ] # signatures are binary, well-formed, and the prover know the signature's value sum_a, sum_b, sum_k = (0, 0, 0) # sum of signatures equals 1 # loop over signatures for i in range(0, len(added_signature)): # encrypt added signature (a, b, k) = binencrypt(params, tally_pub, added_signature[i]) c = (a, b) enc_added_signatures.append(pack(c)) # update new scores new_c = add(unpack(old_signature['scores'][i]), c) new_signature['scores'][i] = pack(new_c) # construct proof of binary tmp1 = provebin(params, tally_pub, (a, b), k, added_signature[i]) proof_bin.append(pack(tmp1)) # update sum of signature if i == 0: sum_a, sum_b, sum_k = (a, b, k) else: sum_c = (sum_a, sum_b) sum_a, sum_b, sum_k = add_side(sum_c, c, sum_k, k) # build proof that sum of signatures equals 1 sum_c = (sum_a, sum_b) proof_sum = proveone(params, tally_pub, sum_c, sum_k) # compute signature (G, _, _, _) = params hasher = sha256() hasher.update(dumps(old_signature).encode('utf8')) hasher.update(dumps(enc_added_signatures).encode('utf8')) # return return { 'outputs': (dumps(new_signature), ), 'extra_parameters': (dumps(enc_added_signatures), dumps(proof_bin), pack(proof_sum)) }
def auth_transfer_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: amount = loads(parameters[0]) input_from_account = loads(inputs[0]) input_to_account = loads(inputs[1]) output_from_account = loads(outputs[0]) output_to_account = loads(outputs[1]) sig = unpack(parameters[1]) # check format if len(inputs) != 2 or len(reference_inputs) != 0 or len(outputs) != 2 or len(returns) != 0: return False if input_from_account['pub'] != output_from_account['pub'] or input_to_account['pub'] != output_to_account['pub']: return False # check tokens if input_from_account['type'] != 'BankAccount' or input_to_account['type'] != 'BankAccount': return False if output_from_account['type'] != 'BankAccount' or output_to_account['type'] != 'BankAccount': return False # amount transfered should be non-negative if amount < 0: return False # amount transfered should not exceed balance if input_from_account['balance'] < amount: return False # consistency between inputs and outputs if input_from_account['balance'] != output_from_account['balance'] + amount: return False if input_to_account['balance'] != output_to_account['balance'] - amount: return False # hash message to verify signature hasher = sha256() hasher.update(dumps(inputs).encode('utf8')) hasher.update(dumps(reference_inputs).encode('utf8')) hasher.update(dumps(parameters[0]).encode('utf8')) # recompose signed digest pub = unpack(input_from_account['pub']) # verify signature (G, _, _, _) = setup() return do_ecdsa_verify(G, pub, sig, hasher.digest()) return True except (KeyError, Exception): return False
def add_signature_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: print "CHECKING - parameters " + str(parameters) # retrieve petition old_signature = loads(inputs[0]) new_signature = loads(outputs[0]) num_options = len(old_signature['options']) # check format if len(inputs) != 1 or len(reference_inputs) != 0 or len( outputs) != 1 or len(returns) != 0: return False if num_options != len(new_signature['scores']) or num_options != len( new_signature['scores']): return False if old_signature['tally_pub'] != new_signature['tally_pub']: return False print "CHECKING - tokens" if new_signature['type'] != 'PetitionEncObject': return False print "CHECKING - Generate params" # generate params, retrieve tally's public key and the parameters params = setup() tally_pub = unpack(old_signature['tally_pub']) added_signature = loads(parameters[0]) proof_bin = loads(parameters[1]) proof_sum = unpack(parameters[2]) print "CHECKING - verify proofs of binary (Signatures have to be bin values)" for i in range(0, num_options): if not verifybin(params, tally_pub, unpack(added_signature[i]), unpack(proof_bin[i])): return False print "CHECKING - verify proof of sum of signatures (sum of signatures has to be 1)" sum_a, sum_b = unpack(added_signature[-1]) sum_c = (sum_a, sum_b) for i in range(0, num_options - 1): sum_c = add(sum_c, unpack(added_signature[i])) if not verifyone(params, tally_pub, sum_c, proof_sum): return False print "CHECKING - verify that output == input + signature" for i in range(0, num_options): tmp_c = add(unpack(old_signature['scores'][i]), unpack(added_signature[i])) if not new_signature['scores'][i] == pack(tmp_c): return False # otherwise return True except (KeyError, Exception): return False
def compute_bill(inputs, reference_inputs, parameters, readings, openings, tariffs): # get meter meter = loads(inputs[0]) # compute total bill G = setup()[0] total_bill = sum(r * t for r, t in zip(loads(readings), loads(tariffs))) sum_openings = sum( o * t for o, t in zip(unpack(openings), loads(tariffs))) % G.order() # new bill bill = { 'type': 'SMBill', 'info': meter['info'], 'total_bill': total_bill, 'billing_period': meter['billing_period'], 'tariffs': meter['tariffs'] } # return return { 'outputs': (dumps(bill), ), 'extra_parameters': { 'total_bill': dumps(total_bill), 'sum_openings': pack(sum_openings), } }
def tally_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: # retrieve vote vote = loads(inputs[0]) result = loads(outputs[0]) # check format if len(inputs) != 1 or len(reference_inputs) != 0 or len( outputs) != 1 or len(returns) != 0: return False if len(vote['options']) != len(result['outcome']): return False # check tokens if result['type'] != 'VoteResult': return False # generate params, retrieve tally's public key and the parameters params = setup() (G, _, (h0, _, _, _), _) = params tally_pub = unpack(vote['tally_pub']) sig = unpack(parameters['signature']) proof_dec = loads(parameters['proof_dec']) outcome = result['outcome'] # verify proof of correct decryption for i in range(0, len(vote['scores'])): a, b = unpack(vote['scores'][i]) ciphertext = (a, b - outcome[i] * h0) if not verifyzero(params, tally_pub, ciphertext, unpack(proof_dec[i])): return False # verify signature hasher = sha256() hasher.update(dumps(vote).encode('utf8')) hasher.update(dumps(result['outcome']).encode('utf8')) if not do_ecdsa_verify(G, tally_pub, sig, hasher.digest()): return False # otherwise return True except (KeyError, Exception): return False
def add_reading_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: # get objects old_meter = loads(inputs[0]) new_meter = loads(outputs[0]) # check format if len(inputs) != 1 or len(reference_inputs) != 0 or len( outputs) != 1 or len(returns) != 0: return False if old_meter['pub'] != new_meter['pub'] or old_meter[ 'info'] != new_meter['info']: return False if old_meter['tariffs'] != new_meter['tariffs'] or old_meter[ 'billing_period'] != new_meter['billing_period']: return False # check tokens if old_meter['type'] != new_meter['type']: return False # check readings' consistency if new_meter['readings'] != old_meter['readings'] + [ parameters['reading'] ]: return False # hash message to sign hasher = sha256() hasher.update(dumps(old_meter).encode('utf8')) hasher.update(dumps(parameters['reading']).encode('utf8')) # verify signature G = setup()[0] pub = unpack(old_meter['pub']) sig = unpack(parameters['signature']) if not do_ecdsa_verify(G, pub, sig, hasher.digest()): return False # otherwise return True except (KeyError, Exception): return False
def generate_sig(priv, msg="proof"): hasher = sha256() hasher.update(msg) # sign message G = setup()[0] sig = do_ecdsa_sign(G, unpack(priv), hasher.digest()) return pack(sig)
def compute_bill_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: # get objects meter = loads(inputs[0]) bill = loads(outputs[0]) # check format if len(inputs) != 1 or len(reference_inputs) != 0 or len( outputs) != 1 or len(returns) != 0: return False if meter['billing_period'] != bill['billing_period'] or meter[ 'info'] != bill['info']: return False if meter['tariffs'] != bill['tariffs']: return False if bill['total_bill'] != loads(parameters['total_bill']): return False # check tokens if bill['type'] != 'SMBill': return False # get objects tariffs = bill['tariffs'] commitements = meter['readings'] sum_openings = unpack(parameters['sum_openings']) total_bill = loads(parameters['total_bill']) # verify bill (G, g, (h0, _, _, _), _) = setup() bill_commitment = G.infinite() for i in range(0, len(commitements)): bill_commitment = bill_commitment + tariffs[i] * unpack( commitements[i]) if bill_commitment - sum_openings * h0 != total_bill * g: return False # otherwise return True except (KeyError, Exception): return False
def submit_bid_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: input_token = loads(inputs[0]) output_token = loads(outputs[0]) output_bid = loads(outputs[1]) smart_meter = loads(reference_inputs[0]) # check format if len(inputs) != 1 or len(reference_inputs) != 1 or len(outputs) != 2 or len(parameters) != 2 or len(returns) != 0: return False # check tokens if input_token['type'] != 'EBToken' or output_token['type'] != 'EBToken': return False if output_bid['type'] != 'EBBuy' and output_bid['type'] != 'EBSell': return False if smart_meter['type'] != 'SMMeter': return False if output_bid['pub'] != smart_meter['pub']: return False # hash message to verify signature hasher = sha256() hasher.update(dumps(input_token).encode('utf8')) hasher.update(dumps(smart_meter).encode('utf8')) hasher.update(dumps(output_bid).encode('utf8')) # recompose signed digest pub = unpack(smart_meter['pub']) sig = unpack(parameters[1]) # verify signature (G, _, _, _) = setup() if not do_ecdsa_verify(G, pub, sig, hasher.digest()): return False # otherwise return True except (KeyError, Exception): return False
def create_vote_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: # retrieve vote vote = loads(outputs[1]) num_votes = len(vote['options']) # check format if len(inputs) != 1 or len(reference_inputs) != 0 or len( outputs) != 2 or len(returns) != 0: return False if num_votes < 1 or num_votes != len(vote['scores']): return False if vote['participants'] == None: return False # check tokens if loads(inputs[0])['type'] != 'VoteToken' or loads( outputs[0])['type'] != 'VoteToken': return False if vote['type'] != 'VoteObject': return False # check proof params = setup() proof_init = unpack(parameters['proof_init']) tally_pub = unpack(vote['tally_pub']) for value in vote['scores']: if not verifyzero(params, tally_pub, unpack(value), proof_init): return False # otherwise return True except (KeyError, Exception): return False
def submit_bid(inputs, reference_inputs, parameters, meter_priv): # Extract bid object from paramters bid = loads(parameters[0]) smart_meter = loads(reference_inputs[0]) token = loads(inputs[0]) bid['pub'] = smart_meter['pub'] # Create a hash digest of inputs and parameters hasher = sha256() hasher.update(dumps(token).encode('utf8')) hasher.update(dumps(smart_meter).encode('utf8')) hasher.update(dumps(bid).encode('utf8')) # sign message G = setup()[0] sig = do_ecdsa_sign(G, unpack(meter_priv), hasher.digest()) # return return { 'outputs': (inputs[0],dumps(bid)), 'extra_parameters' : ( pack(sig), ) }
def auth_transfer(inputs, reference_inputs, parameters, priv): # compute outputs amount = loads(parameters[0]) new_from_account = loads(inputs[0]) new_to_account = loads(inputs[1]) new_from_account["balance"] -= amount new_to_account["balance"] += amount # hash message to sign hasher = sha256() hasher.update(dumps(inputs).encode('utf8')) hasher.update(dumps(reference_inputs).encode('utf8')) hasher.update(dumps(parameters[0]).encode('utf8')) # sign message G = setup()[0] sig = do_ecdsa_sign(G, unpack(priv), hasher.digest()) # return return { 'outputs': (dumps(new_from_account), dumps(new_to_account)), 'extra_parameters' : (pack(sig),) }
def tally(inputs, reference_inputs, parameters, tally_priv, tally_pub): # retrieve last vote vote = loads(inputs[0]) # generate params & retrieve tally's public key params = setup() table = make_table(params) (G, _, (h0, _, _, _), _) = params # decrypt aggregated results outcome = [] for item in vote['scores']: outcome.append(dec(params, table, unpack(tally_priv), unpack(item))) # proof of decryption proof_dec = [] for i in range(0, len(vote['scores'])): a, b = unpack(vote['scores'][i]) ciphertext = (a, b - outcome[i] * h0) tmp = provezero(params, unpack(tally_pub), ciphertext, unpack(tally_priv)) proof_dec.append(pack(tmp)) # signature hasher = sha256() hasher.update(dumps(vote).encode('utf8')) hasher.update(dumps(outcome).encode('utf8')) sig = do_ecdsa_sign(G, unpack(tally_priv), hasher.digest()) # pack result result = {'type': 'VoteResult', 'outcome': outcome} # return return { 'outputs': (dumps(result), ), 'extra_parameters': { 'proof_dec': dumps(proof_dec), 'signature': pack(sig) } }
def add_vote(inputs, reference_inputs, parameters, added_vote, voter_priv, voter_pub): # retrieve old vote & init new vote object old_vote = loads(inputs[0]) new_vote = loads(inputs[0]) added_vote = loads(added_vote) # generate params & retrieve tally's public key params = setup() tally_pub = unpack(old_vote['tally_pub']) # encrypt votes & proofs to build enc_added_votes = [] # encrypted votes proof_bin = [ ] # votes are binary, well-formed, and the prover know the vote's value sum_a, sum_b, sum_k = (0, 0, 0) # sum of votes equals 1 # loop over votes for i in range(0, len(added_vote)): # encrypt added vote (a, b, k) = binencrypt(params, tally_pub, added_vote[i]) c = (a, b) enc_added_votes.append(pack(c)) # update new scores new_c = add(unpack(old_vote['scores'][i]), c) new_vote['scores'][i] = pack(new_c) # construct proof of binary tmp1 = provebin(params, tally_pub, (a, b), k, added_vote[i]) proof_bin.append(pack(tmp1)) # update sum of votes if i == 0: sum_a, sum_b, sum_k = (a, b, k) else: sum_c = (sum_a, sum_b) sum_a, sum_b, sum_k = add_side(sum_c, c, sum_k, k) # build proof that sum of votes equals 1 sum_c = (sum_a, sum_b) proof_sum = proveone(params, tally_pub, sum_c, sum_k) # remove voter from participants new_vote['participants'].remove(voter_pub) # compute signature (G, _, _, _) = params hasher = sha256() hasher.update(dumps(old_vote).encode('utf8')) hasher.update(dumps(enc_added_votes).encode('utf8')) sig = do_ecdsa_sign(G, unpack(voter_priv), hasher.digest()) # return return { 'outputs': (dumps(new_vote), ), 'extra_parameters': { 'votes': dumps(enc_added_votes), 'signature': pack(sig), 'voter_pub': voter_pub, # already packed 'proof_bin': dumps(proof_bin), 'proof_sum': pack(proof_sum) } }
def add_vote_checker(inputs, reference_inputs, parameters, outputs, returns, dependencies): try: # retrieve vote old_vote = loads(inputs[0]) new_vote = loads(outputs[0]) num_votes = len(old_vote['options']) # check format if len(inputs) != 1 or len(reference_inputs) != 0 or len( outputs) != 1 or len(returns) != 0: return False if num_votes != len(new_vote['scores']) or num_votes != len( new_vote['scores']): return False if new_vote['participants'] == None: return False if old_vote['tally_pub'] != new_vote['tally_pub']: return False # check tokens if new_vote['type'] != 'VoteObject': return False # check that voter has been removed from participants if not parameters['voter_pub'] in old_vote['participants']: return False if parameters['voter_pub'] in new_vote['participants']: return False if len(old_vote['participants']) != len(new_vote['participants']) + 1: return False # generate params, retrieve tally's public key and the parameters params = setup() tally_pub = unpack(old_vote['tally_pub']) added_vote = loads(parameters['votes']) sig = unpack(parameters['signature']) voter_pub = unpack(parameters['voter_pub']) proof_bin = loads(parameters['proof_bin']) proof_sum = unpack(parameters['proof_sum']) # verify signature (G, _, _, _) = params hasher = sha256() hasher.update(dumps(old_vote).encode('utf8')) hasher.update(dumps(added_vote).encode('utf8')) if not do_ecdsa_verify(G, voter_pub, sig, hasher.digest()): return False # verify proofs of binary (votes have to be bin values) for i in range(0, num_votes): if not verifybin(params, tally_pub, unpack(added_vote[i]), unpack(proof_bin[i])): return False # verify proof of sum of votes (sum of votes has to be 1) sum_a, sum_b = unpack(added_vote[-1]) sum_c = (sum_a, sum_b) for i in range(0, num_votes - 1): sum_c = add(sum_c, unpack(added_vote[i])) if not verifyone(params, tally_pub, sum_c, proof_sum): return False # verify that output == input + vote for i in range(0, num_votes): tmp_c = add(unpack(old_vote['scores'][i]), unpack(added_vote[i])) if not new_vote['scores'][i] == pack(tmp_c): return False # otherwise return True except (KeyError, Exception): return False