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/>.
"""
from typing import Optional, Dict
from bytestring_splitter import BytestringKwargifier, VariableLengthBytestring
@ -128,9 +129,6 @@ class MessageKit(CryptoKit):
def signature(self):
return self._signature
def __bytes__(self):
return bytes(self.capsule) + VariableLengthBytestring(self.ciphertext)
class PolicyMessageKit(MessageKit):
"""

View File

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

View File

@ -16,18 +16,22 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import contextlib
import time
from collections import defaultdict, deque
from contextlib import suppress
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 requests
import time
from bytestring_splitter import (
BytestringSplitter,
PartiallyKwargifiedBytes,
VariableLengthBytestring,
VariableLengthBytestring
)
from bytestring_splitter import (
BytestringSplittingError
)
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.powers import DecryptingPower, NoSigningPower, SigningPower
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.network import LEARNING_LOOP_VERSION
from nucypher.network.exceptions import NodeSeemsToBeDown
from nucypher.network.middleware import RestMiddleware
from nucypher.network.protocols import SuspiciousActivity
from nucypher.utilities.logging import Logger
from nucypher.crypto.umbral_adapter import Signature
TEACHER_NODES = {
NetworksInventory.MAINNET: (
@ -270,7 +274,8 @@ class Learner:
from nucypher.characters.lawful import 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()
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.
except NodeSeemsToBeDown as e:
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
except current_teacher.InvalidNode as e:
# Ugh. The teacher is invalid. Rough.
@ -824,10 +830,12 @@ class Learner:
# TODO: Sort this out.
return RELAX
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
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
finally:
# 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 uuid
import weakref
@ -29,12 +28,14 @@ from flask import Flask, Response, jsonify, request
from mako import exceptions as mako_exceptions
from mako.template import Template
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.crypto.keypairs import HostingKeypair
from nucypher.crypto.kits import PolicyMessageKit
from nucypher.crypto.powers import KeyPairBasedPower, PowerUpError
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.models import PolicyArrangement, TreasureMap, Workorder
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.")
return Response(response='KeyFrag deleted!', status=200)
@rest_app.route('/reencrypt/<id_as_hex>/', methods=["POST"])
def reencrypt(id_as_hex):
# 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)
@rest_app.route('/reencrypt', methods=["POST"])
def reencrypt():
# Get Work Order
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 = WorkOrder.from_rest_payload(arrangement_id=arrangement_id,
rest_payload=work_order_payload,
ursula=this_node,
alice_address=alice_address)
work_order = WorkOrder.from_rest_payload(rest_payload=work_order_payload, ursula=this_node)
log.info(f"Work Order from {work_order.bob}, signed {work_order.receipt_signature}")
# Get KFrag
encrypted_kfrag = work_order.kfrag
kfrag = this_node.verify_from(alice_verifying_key, encrypted_kfrag, decrypt=True)
if not kfrag.verify(signing_pubkey=alice_verifying_key): # TODO: Maybe this check is redundant?
return Response(response="{} is invalid".format(kfrag), status=422) # TODO: Maybe good, ol' 400 is OK.
# Deserialize Entities
authorizer = Alice.from_public_keys(verifying_key=work_order.authorizer_verifying_key)
authorizer_verifying_key = authorizer.stamp.as_umbral_pubkey()
kfrag_kit = PolicyMessageKit.from_bytes(work_order.encrypted_kfrag)
# 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
response = this_node._reencrypt(kfrag=kfrag,
work_order=work_order,
alice_verifying_key=alice_verifying_key)
alice_verifying_key=authorizer_verifying_key)
# Now, Ursula saves this workorder to her database...
# 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:
new_workorder.arrangement_id = work_order.arrangement_id
work_order_id = str(uuid.uuid4())
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_signature = work_order.receipt_signature
new_workorder.bob_signature = work_order.receipt_signature # Handle for challenge protocol
headers = {'Content-Type': 'application/octet-stream'}
return Response(headers=headers, response=response)