Use a unified method of MessageKit bytes serialization; remove '__bytes__'.

pull/2687/head
Kieran Prasch 2021-03-26 09:33:28 -07:00 committed by Kieran R. Prasch
parent 8c12304944
commit 6c29fd05c9
4 changed files with 45 additions and 48 deletions

View File

@ -15,6 +15,7 @@ You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>. along with nucypher. If not, see <https://www.gnu.org/licenses/>.
""" """
from typing import Optional, Dict from typing import Optional, Dict
from bytestring_splitter import BytestringKwargifier, VariableLengthBytestring from bytestring_splitter import BytestringKwargifier, VariableLengthBytestring
@ -128,9 +129,6 @@ class MessageKit(CryptoKit):
def signature(self): def signature(self):
return self._signature return self._signature
def __bytes__(self):
return bytes(self.capsule) + VariableLengthBytestring(self.ciphertext)
class PolicyMessageKit(MessageKit): class PolicyMessageKit(MessageKit):
""" """

View File

@ -227,10 +227,9 @@ class RestMiddleware:
def send_work_order_payload_to_ursula(self, work_order): def send_work_order_payload_to_ursula(self, work_order):
payload = work_order.payload() payload = work_order.payload()
id_as_hex = work_order.arrangement_id.hex()
response = self.client.post( response = self.client.post(
node_or_sprout=work_order.ursula, node_or_sprout=work_order.ursula,
path=f"reencrypt/{id_as_hex}", path=f"reencrypt",
data=payload, data=payload,
timeout=2 timeout=2
) )

View File

@ -16,18 +16,22 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
""" """
import contextlib import contextlib
import time
from collections import defaultdict, deque from collections import defaultdict, deque
from contextlib import suppress from contextlib import suppress
from queue import Queue from queue import Queue
from typing import Iterable, List, Set, Tuple, Union, Callable from typing import Callable
from typing import Iterable, List
from typing import Set, Tuple, Union
import maya import maya
import requests import requests
import time
from bytestring_splitter import ( from bytestring_splitter import (
BytestringSplitter, BytestringSplitter,
PartiallyKwargifiedBytes, PartiallyKwargifiedBytes,
VariableLengthBytestring, VariableLengthBytestring
)
from bytestring_splitter import (
BytestringSplittingError BytestringSplittingError
) )
from constant_sorrow import constant_or_bytes from constant_sorrow import constant_or_bytes
@ -58,13 +62,13 @@ from nucypher.config.storages import ForgetfulNodeStorage
from nucypher.crypto.kits import UmbralMessageKit from nucypher.crypto.kits import UmbralMessageKit
from nucypher.crypto.powers import DecryptingPower, NoSigningPower, SigningPower from nucypher.crypto.powers import DecryptingPower, NoSigningPower, SigningPower
from nucypher.crypto.splitters import signature_splitter from nucypher.crypto.splitters import signature_splitter
from nucypher.crypto.umbral_adapter import Signature
from nucypher.crypto.utils import recover_address_eip_191, verify_eip_191 from nucypher.crypto.utils import recover_address_eip_191, verify_eip_191
from nucypher.network import LEARNING_LOOP_VERSION from nucypher.network import LEARNING_LOOP_VERSION
from nucypher.network.exceptions import NodeSeemsToBeDown from nucypher.network.exceptions import NodeSeemsToBeDown
from nucypher.network.middleware import RestMiddleware from nucypher.network.middleware import RestMiddleware
from nucypher.network.protocols import SuspiciousActivity from nucypher.network.protocols import SuspiciousActivity
from nucypher.utilities.logging import Logger from nucypher.utilities.logging import Logger
from nucypher.crypto.umbral_adapter import Signature
TEACHER_NODES = { TEACHER_NODES = {
NetworksInventory.MAINNET: ( NetworksInventory.MAINNET: (
@ -270,7 +274,8 @@ class Learner:
from nucypher.characters.lawful import Ursula from nucypher.characters.lawful import Ursula
self.node_class = node_class or Ursula self.node_class = node_class or Ursula
self.node_class.set_cert_storage_function(node_storage.store_node_certificate) # TODO: Fix this temporary workaround for on-disk cert storage. #1481 self.node_class.set_cert_storage_function(
node_storage.store_node_certificate) # TODO: Fix this temporary workaround for on-disk cert storage. #1481
known_nodes = known_nodes or tuple() known_nodes = known_nodes or tuple()
self.unresponsive_startup_nodes = list() # TODO: Buckets - Attempt to use these again later #567 self.unresponsive_startup_nodes = list() # TODO: Buckets - Attempt to use these again later #567
@ -808,7 +813,8 @@ class Learner:
# These except clauses apply to the current_teacher itself, not the learned-about nodes. # These except clauses apply to the current_teacher itself, not the learned-about nodes.
except NodeSeemsToBeDown as e: except NodeSeemsToBeDown as e:
unresponsive_nodes.add(current_teacher) unresponsive_nodes.add(current_teacher)
self.log.info(f"Teacher {str(current_teacher)} is perhaps down:{e}.") # FIXME: This was printing the node bytestring. Is this really necessary? #1712 self.log.info(
f"Teacher {str(current_teacher)} is perhaps down:{e}.") # FIXME: This was printing the node bytestring. Is this really necessary? #1712
return return
except current_teacher.InvalidNode as e: except current_teacher.InvalidNode as e:
# Ugh. The teacher is invalid. Rough. # Ugh. The teacher is invalid. Rough.
@ -824,10 +830,12 @@ class Learner:
# TODO: Sort this out. # TODO: Sort this out.
return RELAX return RELAX
else: else:
self.log.warn(f"Unhandled error while learning from {str(current_teacher)}: {bytes(current_teacher)}:{e}.") self.log.warn(
f"Unhandled error while learning from {str(current_teacher)}: {bytes(current_teacher)}:{e}.")
raise raise
except Exception as e: except Exception as e:
self.log.warn(f"Unhandled error while learning from {str(current_teacher)}: {bytes(current_teacher)}:{e}.") # To track down 2345 / 1698 self.log.warn(
f"Unhandled error while learning from {str(current_teacher)}: {bytes(current_teacher)}:{e}.") # To track down 2345 / 1698
raise raise
finally: finally:
# Is cycling happening in the right order? # Is cycling happening in the right order?

View File

@ -16,7 +16,6 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
""" """
import binascii
import os import os
import uuid import uuid
import weakref import weakref
@ -29,12 +28,14 @@ from flask import Flask, Response, jsonify, request
from mako import exceptions as mako_exceptions from mako import exceptions as mako_exceptions
from mako.template import Template from mako.template import Template
from maya import MayaDT from maya import MayaDT
from umbral.key_frag import KeyFrag
from nucypher.blockchain.eth.constants import NULL_ADDRESS
from nucypher.config.constants import MAX_UPLOAD_CONTENT_LENGTH from nucypher.config.constants import MAX_UPLOAD_CONTENT_LENGTH
from nucypher.crypto.keypairs import HostingKeypair from nucypher.crypto.keypairs import HostingKeypair
from nucypher.crypto.kits import PolicyMessageKit
from nucypher.crypto.powers import KeyPairBasedPower, PowerUpError from nucypher.crypto.powers import KeyPairBasedPower, PowerUpError
from nucypher.crypto.signing import InvalidSignature from nucypher.crypto.signing import InvalidSignature
from nucypher.crypto.utils import canonical_address_from_umbral_key
from nucypher.datastore.datastore import Datastore, RecordNotFound, DatastoreTransactionError from nucypher.datastore.datastore import Datastore, RecordNotFound, DatastoreTransactionError
from nucypher.datastore.models import PolicyArrangement, TreasureMap, Workorder from nucypher.datastore.models import PolicyArrangement, TreasureMap, Workorder
from nucypher.network import LEARNING_LOOP_VERSION from nucypher.network import LEARNING_LOOP_VERSION
@ -237,51 +238,42 @@ def _make_rest_app(datastore: Datastore, this_node, domain: str, log: Logger) ->
log.info("KeyFrag successfully removed.") log.info("KeyFrag successfully removed.")
return Response(response='KeyFrag deleted!', status=200) return Response(response='KeyFrag deleted!', status=200)
@rest_app.route('/reencrypt/<id_as_hex>/', methods=["POST"]) @rest_app.route('/reencrypt', methods=["POST"])
def reencrypt(id_as_hex): def reencrypt():
# Get Policy Arrangement
try:
arrangement_id = binascii.unhexlify(id_as_hex)
except (binascii.Error, TypeError):
return Response(response=b'Invalid arrangement ID', status=405)
# TODO: Verify payment
try:
# Get KeyFrag
# TODO: Yeah, well, what if this arrangement hasn't been enacted? 1702
with datastore.describe(PolicyArrangement, id_as_hex) as policy_arrangement:
alice_verifying_key = policy_arrangement.alice_verifying_key
except RecordNotFound:
return Response(response=arrangement_id, status=404)
# Get Work Order # Get Work Order
from nucypher.policy.collections import WorkOrder # Avoid circular import from nucypher.policy.collections import WorkOrder # Avoid circular import
alice_address = canonical_address_from_umbral_key(alice_verifying_key)
work_order_payload = request.data work_order_payload = request.data
work_order = WorkOrder.from_rest_payload(arrangement_id=arrangement_id, work_order = WorkOrder.from_rest_payload(rest_payload=work_order_payload, ursula=this_node)
rest_payload=work_order_payload,
ursula=this_node,
alice_address=alice_address)
log.info(f"Work Order from {work_order.bob}, signed {work_order.receipt_signature}") log.info(f"Work Order from {work_order.bob}, signed {work_order.receipt_signature}")
# Get KFrag # Deserialize Entities
encrypted_kfrag = work_order.kfrag authorizer = Alice.from_public_keys(verifying_key=work_order.authorizer_verifying_key)
kfrag = this_node.verify_from(alice_verifying_key, encrypted_kfrag, decrypt=True) authorizer_verifying_key = authorizer.stamp.as_umbral_pubkey()
if not kfrag.verify(signing_pubkey=alice_verifying_key): # TODO: Maybe this check is redundant? kfrag_kit = PolicyMessageKit.from_bytes(work_order.encrypted_kfrag)
return Response(response="{} is invalid".format(kfrag), status=422) # TODO: Maybe good, ol' 400 is OK.
# Verify & Decrypt KFrag
# TODO: Cache the result of kfrag verification for optimization
kfrag_plaintext = this_node.verify_from(stranger=authorizer, message_kit=kfrag_kit, decrypt=True)
kfrag = KeyFrag.from_bytes(kfrag_plaintext)
if not kfrag.verify(signing_pubkey=authorizer_verifying_key):
log.info(f"Invalid KFrag detected - sender {authorizer_verifying_key.to_bytes().hex()}")
return Response(response="{} is invalid".format(kfrag), status=401)
# TODO: Verify policy payment
# TODO: Cache the result of payment verification for optimization
# Re-encrypt # Re-encrypt
response = this_node._reencrypt(kfrag=kfrag, response = this_node._reencrypt(kfrag=kfrag,
work_order=work_order, work_order=work_order,
alice_verifying_key=alice_verifying_key) alice_verifying_key=authorizer_verifying_key)
# Now, Ursula saves this workorder to her database... # Now, Ursula saves this workorder to her database...
# Note: we give the work order a random ID to store it under. # Note: we give the work order a random ID to store it under.
with datastore.describe(Workorder, str(uuid.uuid4()), writeable=True) as new_workorder: work_order_id = str(uuid.uuid4())
new_workorder.arrangement_id = work_order.arrangement_id with datastore.describe(Workorder, work_order_id, writeable=True) as new_workorder:
new_workorder.bob_verifying_key = work_order.bob.stamp.as_umbral_pubkey() new_workorder.bob_verifying_key = work_order.bob.stamp.as_umbral_pubkey()
new_workorder.bob_signature = work_order.receipt_signature new_workorder.bob_signature = work_order.receipt_signature # Handle for challenge protocol
headers = {'Content-Type': 'application/octet-stream'} headers = {'Content-Type': 'application/octet-stream'}
return Response(headers=headers, response=response) return Response(headers=headers, response=response)