Modifies behaviour towards a failed EncryptedBlob decrpytion

The decryption for the `EncryptedBlob` using AES-GCM-128 (the only cipher available atm) raises an `InvalidTag` exception. This was not properly captured by the watcher making it crash. This behavior was already discovered during the `EncryptedBlob` unit testing and left to be fixed in the `Watcher` unit testing.

However, making the EncryptedBlob raise such an exception may not be a good practice, since other ciphers may run into different exceptions. Therefore, the `EncryptedBlob` has been modified to return None upon facing a decryption issue, the `BlockProcessor` will detect that and return a None justice_txm and justice_txid. Upon receiving a None `justice_txid` the `Watcher` will delete the appointment without notifiying the `Responder`.
This commit is contained in:
Sergi Delgado Segura
2019-10-14 16:34:41 +01:00
parent d43ab76220
commit d7c89ddc91
4 changed files with 26 additions and 18 deletions

View File

@@ -74,15 +74,17 @@ class BlockProcessor:
# ToDo: #20-test-tx-decrypting-edge-cases
justice_rawtx = appointments[uuid].encrypted_blob.decrypt(dispute_txid)
justice_txid = bitcoin_cli.decoderawtransaction(justice_rawtx).get('txid')
matches.append((locator, uuid, dispute_txid, justice_txid, justice_rawtx))
logger.info("Match found for locator.", locator=locator, uuid=uuid, justice_txid=justice_txid)
except JSONRPCException as e:
# Tx decode failed returns error code -22, maybe we should be more strict here. Leaving it simple
# for the POC
justice_txid = None
justice_rawtx = None
logger.error("Can't build transaction from decoded data.", error=e.error)
matches.append((locator, uuid, dispute_txid, justice_txid, justice_rawtx))
return matches
# DISCUSS: This method comes from the Responder and seems like it could go back there.

View File

@@ -1,6 +1,8 @@
from hashlib import sha256
from binascii import unhexlify, hexlify
from cryptography.exceptions import InvalidTag
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from pisa.logger import Logger
logger = Logger("Watcher")
@@ -33,7 +35,12 @@ class EncryptedBlob:
# Decrypt
aesgcm = AESGCM(sk)
data = unhexlify(self.data.encode())
try:
raw_tx = aesgcm.decrypt(nonce=nonce, data=data, associated_data=None)
hex_raw_tx = hexlify(raw_tx).decode('utf8')
except InvalidTag:
hex_raw_tx = None
return hex_raw_tx

View File

@@ -49,7 +49,7 @@ class Watcher:
if self.asleep:
self.asleep = False
self.block_queue = Queue()
zmq_thread = Thread(target=self.do_subscribe, args=[self.block_queue])
zmq_thread = Thread(target=self.do_subscribe)
watcher = Thread(target=self.do_watch)
zmq_thread.start()
watcher.start()
@@ -67,9 +67,9 @@ class Watcher:
return appointment_added
def do_subscribe(self, block_queue):
def do_subscribe(self):
self.zmq_subscriber = ZMQHandler(parent="Watcher")
self.zmq_subscriber.handle(block_queue)
self.zmq_subscriber.handle(self.block_queue)
def do_watch(self):
while len(self.appointments) > 0:
@@ -92,8 +92,10 @@ class Watcher:
matches = BlockProcessor.get_matches(potential_matches, self.locator_uuid_map, self.appointments)
for locator, uuid, dispute_txid, justice_txid, justice_rawtx in matches:
logger.info("Notifying responder and deleting appointment.",
justice_txid=justice_txid, locator=locator, uuid=uuid)
# Errors decrypting the Blob will result in a None justice_txid
if justice_txid is not None:
logger.info("Notifying responder and deleting appointment.", justice_txid=justice_txid,
locator=locator, uuid=uuid)
self.responder.add_response(uuid, dispute_txid, justice_txid, justice_rawtx,
self.appointments[uuid].end_time)

View File

@@ -19,13 +19,10 @@ def test_decrypt():
encrypted_data = urandom(64).hex()
encrypted_blob = EncryptedBlob(encrypted_data)
# Trying to decrypt random data (in AES_GCM-128) should result in an InvalidTag exception
try:
encrypted_blob.decrypt(key)
assert False, "Able to decrypt random data with random key"
except InvalidTag:
assert True
# Trying to decrypt random data (in AES_GCM-128) should result in an InvalidTag exception. Our decrypt function
# returns None
hex_tx = encrypted_blob.decrypt(key)
assert hex_tx is None
# Valid data should run with no InvalidTag and verify
data = "6097cdf52309b1b2124efeed36bd34f46dc1c25ad23ac86f28380f746254f777"