From 2f67ecfa6e784ac4af08afdf49ac43f123eaa1aa Mon Sep 17 00:00:00 2001 From: Sergi Delgado Segura Date: Mon, 16 Dec 2019 10:54:13 +0100 Subject: [PATCH] Changes sk_path to sk_der in Watcher The Watcher used to receive a secret key file path ion the __init__ to load a secret key for signing. That made testing the Watcher hard, since the file needed to be present. Changing it so the main (pisad) loads the file from disk and passes the data the Watcher on init. --- pisa/pisad.py | 7 +++++-- pisa/watcher.py | 14 ++++---------- test/unit/test_api.py | 17 +++++++++++++++-- test/unit/test_watcher.py | 33 +++++++++++++++++---------------- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/pisa/pisad.py b/pisa/pisad.py index fc09f6b..0e8160b 100644 --- a/pisa/pisad.py +++ b/pisa/pisad.py @@ -7,7 +7,7 @@ from pisa.logger import Logger from pisa.api import start_api from pisa.watcher import Watcher from pisa.builder import Builder -from pisa.conf import BTC_NETWORK +from pisa.conf import BTC_NETWORK, PISA_SECRET_KEY from pisa.responder import Responder from pisa.db_manager import DBManager from pisa.block_processor import BlockProcessor @@ -49,7 +49,10 @@ if __name__ == "__main__": watcher_appointments_data = db_manager.load_watcher_appointments() responder_trackers_data = db_manager.load_responder_trackers() - watcher = Watcher(db_manager) + with open(PISA_SECRET_KEY, "rb") as key_file: + secret_key_der = key_file.read() + + watcher = Watcher(db_manager, secret_key_der) if len(watcher_appointments_data) == 0 and len(responder_trackers_data) == 0: logger.info("Fresh bootstrap") diff --git a/pisa/watcher.py b/pisa/watcher.py index 15797b0..25c7db8 100644 --- a/pisa/watcher.py +++ b/pisa/watcher.py @@ -10,7 +10,7 @@ from pisa.cleaner import Cleaner from pisa.responder import Responder from pisa.block_processor import BlockProcessor from pisa.utils.zmq_subscriber import ZMQSubscriber -from pisa.conf import EXPIRY_DELTA, MAX_APPOINTMENTS, PISA_SECRET_KEY +from pisa.conf import EXPIRY_DELTA, MAX_APPOINTMENTS logger = Logger("Watcher") @@ -32,7 +32,7 @@ class Watcher: Args: db_manager (:obj:`DBManager `): a ``DBManager`` instance to interact with the database. - pisa_sk_file (:obj:`str`): a path to the private key used to sign appointment receipts (signaling acceptance). + sk_der (:obj:`bytes`): a DER encoded private key used to sign appointment receipts (signaling acceptance). responder (:obj:`Responder `): a ``Responder`` instance. If ``None`` is passed, a new instance is created. Populated instances are useful when bootstrapping the system from backed-up data. max_appointments(:obj:`int`): the maximum amount of appointments that the :obj:`Watcher` will keep at any given @@ -58,7 +58,7 @@ class Watcher: """ - def __init__(self, db_manager, pisa_sk_file=PISA_SECRET_KEY, responder=None, max_appointments=MAX_APPOINTMENTS): + def __init__(self, db_manager, sk_der, responder=None, max_appointments=MAX_APPOINTMENTS): self.appointments = dict() self.locator_uuid_map = dict() self.asleep = True @@ -66,17 +66,11 @@ class Watcher: self.max_appointments = max_appointments self.zmq_subscriber = None self.db_manager = db_manager + self.signing_key = Cryptographer.load_private_key_der(sk_der) if not isinstance(responder, Responder): self.responder = Responder(db_manager) - if pisa_sk_file is None: - raise ValueError("No signing key provided. Please fix your pisa.conf") - else: - with open(PISA_SECRET_KEY, "rb") as key_file: - secret_key_der = key_file.read() - self.signing_key = Cryptographer.load_private_key_der(secret_key_der) - @staticmethod def compute_locator(tx_id): """ diff --git a/test/unit/test_api.py b/test/unit/test_api.py index d7d2462..c7ed0ad 100644 --- a/test/unit/test_api.py +++ b/test/unit/test_api.py @@ -3,6 +3,7 @@ import pytest import requests from time import sleep from threading import Thread +from cryptography.hazmat.primitives import serialization from pisa.api import start_api from pisa.watcher import Watcher @@ -10,7 +11,13 @@ from pisa.tools import bitcoin_cli from pisa import HOST, PORT, c_logger from pisa.conf import MAX_APPOINTMENTS -from test.unit.conftest import generate_block, generate_blocks, get_random_value_hex, generate_dummy_appointment_data +from test.unit.conftest import ( + generate_block, + generate_blocks, + get_random_value_hex, + generate_dummy_appointment_data, + generate_keypair, +) from common.constants import LOCATOR_LEN_BYTES @@ -25,7 +32,13 @@ locator_dispute_tx_map = {} @pytest.fixture(scope="module") def run_api(db_manager): - watcher = Watcher(db_manager) + sk, pk = generate_keypair() + sk_der = sk.private_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ) + watcher = Watcher(db_manager, sk_der) api_thread = Thread(target=start_api, args=[watcher]) api_thread.daemon = True diff --git a/test/unit/test_watcher.py b/test/unit/test_watcher.py index e5fb5ff..cd2db0d 100644 --- a/test/unit/test_watcher.py +++ b/test/unit/test_watcher.py @@ -2,13 +2,20 @@ import pytest from uuid import uuid4 from threading import Thread from queue import Queue, Empty +from cryptography.hazmat.primitives import serialization from pisa import c_logger from pisa.watcher import Watcher from pisa.responder import Responder from pisa.tools import bitcoin_cli -from test.unit.conftest import generate_block, generate_blocks, generate_dummy_appointment, get_random_value_hex -from pisa.conf import EXPIRY_DELTA, PISA_SECRET_KEY, MAX_APPOINTMENTS +from test.unit.conftest import ( + generate_block, + generate_blocks, + generate_dummy_appointment, + get_random_value_hex, + generate_keypair, +) +from pisa.conf import EXPIRY_DELTA, MAX_APPOINTMENTS from common.tools import check_sha256_hex_format from common.cryptographer import Cryptographer @@ -20,15 +27,18 @@ START_TIME_OFFSET = 1 END_TIME_OFFSET = 1 TEST_SET_SIZE = 200 -with open(PISA_SECRET_KEY, "rb") as key_file_der: - sk_der = key_file_der.read() - signing_key = Cryptographer.load_private_key_der(sk_der) - public_key = signing_key.public_key() + +signing_key, public_key = generate_keypair() +sk_der = signing_key.private_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), +) @pytest.fixture(scope="module") def watcher(db_manager): - return Watcher(db_manager) + return Watcher(db_manager, sk_der) @pytest.fixture(scope="module") @@ -69,15 +79,6 @@ def test_init(watcher): assert type(watcher.responder) is Responder -def test_init_no_key(db_manager): - try: - Watcher(db_manager, pisa_sk_file=None) - assert False - - except ValueError: - assert True - - def test_add_appointment(run_bitcoind, watcher): # The watcher automatically fires do_watch and do_subscribe on adding an appointment if it is asleep (initial state) # Avoid this by setting the state to awake.