From cc0c56c15003812cda632593ebe4d4bba8b1d6f9 Mon Sep 17 00:00:00 2001 From: diminator Date: Fri, 8 Apr 2016 10:56:45 +0200 Subject: [PATCH] sign/verify with fulfillments for CREATE/GENESIS --- bigchaindb/util.py | 44 ++++++++++++++++++++--------------- tests/db/test_bigchain_api.py | 5 +++- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/bigchaindb/util.py b/bigchaindb/util.py index bf11f196..dd38cfc2 100644 --- a/bigchaindb/util.py +++ b/bigchaindb/util.py @@ -1,4 +1,4 @@ - +import copy import json import time import multiprocessing as mp @@ -238,24 +238,24 @@ def sign_tx(transaction, sk): """ b = bigchaindb.Bigchain() sk = crypto.SigningKey(sk) - + tx = copy.deepcopy(transaction) common_data = { - 'operation': transaction['transaction']['operation'], - 'timestamp': transaction['transaction']['timestamp'], - 'data': transaction['transaction']['data'], - 'version': transaction['version'], - 'id': transaction['id'] + 'operation': tx['transaction']['operation'], + 'timestamp': tx['transaction']['timestamp'], + 'data': tx['transaction']['data'], + 'version': tx['version'], + 'id': tx['id'] } - for fulfillment in transaction['transaction']['fulfillments']: + for fulfillment in tx['transaction']['fulfillments']: fulfillment_message = common_data.copy() - if transaction['transaction']['operation'] in ['CREATE', 'GENESIS']: + if tx['transaction']['operation'] in ['CREATE', 'GENESIS']: fulfillment_message.update({ 'input': None, 'condition': None }) # sign the fulfillment message - signed_fulfillment = sk.sign(serialize(fulfillment_message)) + parsed_fulfillment = Ed25519Fulfillment(public_key=sk.get_verifying_key()) else: # get previous condition previous_tx = b.get_transaction(fulfillment['input']['txid']) @@ -267,11 +267,11 @@ def sign_tx(transaction, sk): 'condition': conditions[fulfillment['fid']] }) parsed_fulfillment = Fulfillment.from_json(fulfillment_message['condition']['condition']['details']) - parsed_fulfillment.sign(serialize(fulfillment_message), sk) - signed_fulfillment = parsed_fulfillment.serialize_uri() + parsed_fulfillment.sign(serialize(fulfillment_message), sk) + signed_fulfillment = parsed_fulfillment.serialize_uri() fulfillment.update({'fulfillment': signed_fulfillment}) - return transaction + return tx def create_and_sign_tx(private_key, current_owner, new_owner, tx_input, operation='TRANSFER', payload=None): @@ -326,12 +326,18 @@ def verify_signature(signed_transaction): previous_tx = b.get_transaction(fulfillment['input']['txid']) conditions = sorted(previous_tx['transaction']['conditions'], key=lambda d: d['cid']) fulfillment_message['condition'] = conditions[fulfillment['fid']] - # verify the fulfillment (for now lets assume there is only one owner) - is_valid = Fulfillment.from_uri(fulfillment['fulfillment']).validate(serialize(fulfillment_message)) - else: - # verify the signature (for now lets assume there is only one owner) - vk = crypto.VerifyingKey(fulfillment['current_owners'][0]) - is_valid = vk.verify(serialize(fulfillment_message), fulfillment['fulfillment']) + + # verify the fulfillment (for now lets assume there is only one owner) + try: + parsed_fulfillment = Fulfillment.from_uri(fulfillment['fulfillment']) + except Exception: + return False + is_valid = parsed_fulfillment.validate(serialize(fulfillment_message)) + + # if not a `CREATE` transaction + if fulfillment['input']: + is_valid &= parsed_fulfillment.condition.serialize_uri() == \ + fulfillment_message['condition']['condition']['uri'] if not is_valid: return False diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index 4fe3a8a9..c56a535a 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -36,6 +36,8 @@ class TestBigchainApi(object): @pytest.mark.usefixtures('inputs') def test_create_transaction_transfer(self, b, user_vk, user_sk): input_tx = b.get_owned_ids(user_vk).pop() + assert b.verify_signature(b.get_transaction(input_tx)) == True + tx = b.create_transaction(b.me, user_sk, {'txid': input_tx, 'cid': 0}, 'TRANSFER') assert sorted(tx) == sorted(['id', 'transaction', 'version']) @@ -43,7 +45,8 @@ class TestBigchainApi(object): tx_signed = b.sign_transaction(tx, user_sk) - b.verify_signature(tx) + assert b.verify_signature(tx) == False + assert b.verify_signature(tx_signed) == True def test_transaction_hash(self, b): payload = {'cats': 'are awesome'}