From 445bacce0db37543fe561ff3dd9ad1ec1a2e90e0 Mon Sep 17 00:00:00 2001 From: vrde Date: Tue, 23 Feb 2016 18:14:01 +0100 Subject: [PATCH] Move some other code to the util module --- bigchaindb/core.py | 34 +++++++---------------- bigchaindb/crypto.py | 5 ---- bigchaindb/util.py | 51 +++++++++++++++++++++++++++++++++-- tests/db/test_bigchain_api.py | 3 ++- 4 files changed, 61 insertions(+), 32 deletions(-) diff --git a/bigchaindb/core.py b/bigchaindb/core.py index d9f09092..030d831c 100644 --- a/bigchaindb/core.py +++ b/bigchaindb/core.py @@ -8,7 +8,7 @@ import bigchaindb from bigchaindb import util from bigchaindb import config_utils from bigchaindb import exceptions -from bigchaindb.crypto import hash_data, PublicKey, PrivateKey, generate_key_pair +from bigchaindb import crypto class GenesisBlockAlreadyExistsError(Exception): @@ -80,15 +80,9 @@ class Bigchain(object): return util.sign_tx(transaction, private_key) def verify_signature(self, signed_transaction): - """Verify the signature of a transaction + """Verify the signature of a transaction. - A valid transaction should have been signed `current_owner` corresponding private key. - - Args: - signed_transaction (dict): a transaction with the `signature` included. - - Returns: - bool: True if the signature is correct, False otherwise. + Refer to the documentation of ``bigchaindb.crypto.verify_signature`` """ data = signed_transaction.copy() @@ -99,7 +93,7 @@ class Bigchain(object): signature = data.pop('signature') public_key_base58 = signed_transaction['transaction']['current_owner'] - public_key = PublicKey(public_key_base58) + public_key = crypto.PublicKey(public_key_base58) return public_key.verify(util.serialize(data), signature) def write_transaction(self, signed_transaction): @@ -284,15 +278,7 @@ class Bigchain(object): raise exceptions.DoubleSpend('input `{}` was already spent'.format( transaction['transaction']['input'])) - # Check hash of the transaction - calculated_hash = hash_data(util.serialize(transaction['transaction'])) - if calculated_hash != transaction['id']: - raise exceptions.InvalidHash() - - # Check signature - if not self.verify_signature(transaction): - raise exceptions.InvalidSignature() - + util.check_hash_and_signature(transaction) return transaction def is_valid_transaction(self, transaction): @@ -338,8 +324,8 @@ class Bigchain(object): # Calculate the hash of the new block block_data = util.serialize(block) - block_hash = hash_data(block_data) - block_signature = PrivateKey(self.me_private).sign(block_data) + block_hash = util.hash_data(block_data) + block_signature = crypto.PrivateKey(self.me_private).sign(block_data) block = { 'id': block_hash, @@ -363,7 +349,7 @@ class Bigchain(object): """ # 1. Check if current hash is correct - calculated_hash = hash_data(util.serialize(block['block'])) + calculated_hash = util.hash_data(util.serialize(block['block'])) if calculated_hash != block['id']: raise exceptions.InvalidHash() @@ -459,7 +445,7 @@ class Bigchain(object): } vote_data = util.serialize(vote) - signature = PrivateKey(self.me_private).sign(vote_data) + signature = crypto.PrivateKey(self.me_private).sign(vote_data) vote_signed = { 'node_pubkey': self.me, @@ -541,4 +527,4 @@ class Bigchain(object): """ # generates and returns the keys serialized in hex - return generate_key_pair() + return crypto.generate_key_pair() diff --git a/bigchaindb/crypto.py b/bigchaindb/crypto.py index 8eedae65..fcec3686 100644 --- a/bigchaindb/crypto.py +++ b/bigchaindb/crypto.py @@ -1,7 +1,5 @@ # Separate all crypto code so that we can easily test several implementations -import hashlib -import sha3 import binascii import base58 import bitcoin @@ -146,6 +144,3 @@ def generate_key_pair(): return (private_value_base58, public_value_compressed_base58) - -def hash_data(data): - return hashlib.sha3_256(data.encode()).hexdigest() diff --git a/bigchaindb/util.py b/bigchaindb/util.py index f49e51ad..e501ed96 100644 --- a/bigchaindb/util.py +++ b/bigchaindb/util.py @@ -1,9 +1,12 @@ -import multiprocessing as mp +import sha3 + import json import time +import multiprocessing as mp from datetime import datetime -from bigchaindb.crypto import hash_data, PrivateKey +from bigchaindb import exceptions +from bigchaindb.crypto import PrivateKey, PublicKey class ProcessGroup(object): @@ -148,3 +151,47 @@ def sign_tx(transaction, private_key): signed_transaction.update({'signature': signature}) return signed_transaction + +def create_and_sign_tx(private_key, current_owner, new_owner, tx_input, operation='TRANSFER', payload=None): + tx = create_tx(current_owner, new_owner, tx_input, operation, payload) + return sign_tx(private_key, tx) + + +def hash_data(data): + return sha3.sha3_256(data.encode()).hexdigest() + + +def check_hash_and_signature(transaction): + # Check hash of the transaction + calculated_hash = hash_data(serialize(transaction['transaction'])) + if calculated_hash != transaction['id']: + raise exceptions.InvalidHash() + + # Check signature + if not verify_signature(transaction): + raise exceptions.InvalidSignature() + + +def verify_signature(signed_transaction): + """Verify the signature of a transaction + + A valid transaction should have been signed `current_owner` corresponding private key. + + Args: + signed_transaction (dict): a transaction with the `signature` included. + + Returns: + bool: True if the signature is correct, False otherwise. + """ + + data = signed_transaction.copy() + + # if assignee field in the transaction, remove it + if 'assignee' in data: + data.pop('assignee') + + signature = data.pop('signature') + public_key_base58 = signed_transaction['transaction']['current_owner'] + public_key = PublicKey(public_key_base58) + return public_key.verify(serialize(data), signature) + diff --git a/tests/db/test_bigchain_api.py b/tests/db/test_bigchain_api.py index 92878810..10c1a955 100644 --- a/tests/db/test_bigchain_api.py +++ b/tests/db/test_bigchain_api.py @@ -8,7 +8,8 @@ import rethinkdb as r import bigchaindb from bigchaindb import util from bigchaindb import exceptions -from bigchaindb.crypto import hash_data, PrivateKey, PublicKey, generate_key_pair +from bigchaindb.crypto import PrivateKey, PublicKey, generate_key_pair +from bigchaindb.util import hash_data from bigchaindb.voter import Voter from bigchaindb.block import Block