mirror of https://github.com/nucypher/nucypher.git
BytestringSplitter is now its own project.
parent
b35e5b9840
commit
7f21117cb7
|
@ -389,7 +389,7 @@ class Bob(Character):
|
|||
|
||||
# TODO: Make this much prettier
|
||||
header, signature, ursula_pubkey_sig, _hrac, (
|
||||
port, interface, ttl) = dht_value_splitter(value, msgpack_remainder=True)
|
||||
port, interface, ttl) = dht_value_splitter(value, msgpack_remainder=True)
|
||||
|
||||
if header != BYTESTRING_IS_URSULA_IFACE_INFO:
|
||||
raise TypeError("Unknown DHT value. How did this get on the network?")
|
||||
|
@ -442,7 +442,7 @@ class Bob(Character):
|
|||
# TODO: Make this prettier
|
||||
header, _signature_for_ursula, pubkey_sig_alice, hrac, encrypted_treasure_map = \
|
||||
dht_value_splitter(response.content, return_remainder=True)
|
||||
tmap_messaage_kit = MessageKit.from_bytes(encrypted_treasure_map)
|
||||
tmap_messaage_kit = AdventureKit.from_bytes(encrypted_treasure_map)
|
||||
return tmap_messaage_kit
|
||||
else:
|
||||
assert False
|
||||
|
@ -574,8 +574,8 @@ class Ursula(Character, ProxyRESTServer):
|
|||
def interface_dht_value(self):
|
||||
signature = self.stamp(self.interface_hrac())
|
||||
return (
|
||||
BYTESTRING_IS_URSULA_IFACE_INFO + signature + self.stamp + self.interface_hrac()
|
||||
+ msgpack.dumps(self.dht_interface_info())
|
||||
BYTESTRING_IS_URSULA_IFACE_INFO + signature + self.stamp + self.interface_hrac()
|
||||
+ msgpack.dumps(self.dht_interface_info())
|
||||
)
|
||||
|
||||
def interface_hrac(self):
|
||||
|
|
|
@ -125,4 +125,4 @@ def generate_self_signed_certificate(common_name, curve, private_key=None, days_
|
|||
# TODO: What domain here? Not localhost presumably - ENS? #146
|
||||
cert = cert.add_extension(x509.SubjectAlternativeName([x509.DNSName(u"localhost")]), critical=False)
|
||||
cert = cert.sign(private_key, hashes.SHA512(), default_backend())
|
||||
return cert, private_key
|
||||
return cert, private_key
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
from nkms.crypto.constants import PUBLIC_KEY_LENGTH, CAPSULE_LENGTH
|
||||
from nkms.crypto.utils import BytestringSplitter
|
||||
from bytestring_splitter import BytestringSplitter
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.pre import Capsule
|
||||
from nkms.crypto.signature import Signature
|
||||
|
||||
|
||||
key_splitter = BytestringSplitter((UmbralPublicKey, PUBLIC_KEY_LENGTH, {"as_b64": False}))
|
||||
capsule_splitter = BytestringSplitter((Capsule, CAPSULE_LENGTH))
|
||||
capsule_splitter = BytestringSplitter((Capsule, CAPSULE_LENGTH))
|
||||
signature_splitter = BytestringSplitter(Signature)
|
||||
|
|
|
@ -1,131 +1,7 @@
|
|||
from contextlib import suppress
|
||||
from typing import Any
|
||||
|
||||
import msgpack
|
||||
from umbral.keys import UmbralPublicKey
|
||||
|
||||
from nkms.crypto.api import keccak_digest
|
||||
|
||||
|
||||
class BytestringSplitter(object):
|
||||
|
||||
def __init__(self, *message_types):
|
||||
"""
|
||||
:param message_types: A collection of types of messages to parse.
|
||||
"""
|
||||
self.message_types = []
|
||||
if not message_types:
|
||||
raise ValueError(
|
||||
"Can't make a BytestringSplitter unless you specify what to split!")
|
||||
|
||||
for counter, message_type in enumerate(message_types):
|
||||
# message_types can be tuples (with length and kwargs) or just classes.
|
||||
if isinstance(message_types, tuple):
|
||||
# Here, it's a tuple - these are our message types.
|
||||
self.message_types.extend(message_types)
|
||||
|
||||
# We're ready to break out of the loop, because we
|
||||
# already have our message type.
|
||||
|
||||
# However, before we do, let's address a possible mis-step
|
||||
# by the user and offer a better error message.
|
||||
with suppress(IndexError):
|
||||
if isinstance(message_types[counter + 1], int):
|
||||
raise TypeError("You can't specify the length of the message as a direct argument to the constructor. Instead, pass it as the second argument in a tuple (with the class as the first argument)")
|
||||
# OK, cool - break.
|
||||
break
|
||||
else:
|
||||
# OK, it's an object. If it's a tuple, we can just add it.
|
||||
if isinstance(message_type, tuple):
|
||||
self.message_types.append(message_type)
|
||||
else:
|
||||
# Otherwise, it's a class - turn it into a tuple for
|
||||
# compatibility with get_message_meta later.
|
||||
message_type_tuple = message_type,
|
||||
self.message_types.append(message_type_tuple)
|
||||
|
||||
def __call__(self, splittable, return_remainder=False, msgpack_remainder=False):
|
||||
if not any((return_remainder, msgpack_remainder)) and len(self) != len(splittable):
|
||||
raise ValueError(
|
||||
""""Wrong number of bytes to constitute message types {} -
|
||||
need {}, got {} \n Did you mean to return the remainder?""".format(
|
||||
self.message_types, len(self), len(splittable)))
|
||||
if len(self) > len(splittable):
|
||||
raise ValueError(
|
||||
"""Not enough bytes to constitute
|
||||
message types {} - need {}, got {}""".format(self.message_types,
|
||||
len(self),
|
||||
len(splittable)))
|
||||
cursor = 0
|
||||
message_objects = []
|
||||
|
||||
for message_type in self.message_types:
|
||||
message_class, message_length, kwargs = self.get_message_meta(message_type)
|
||||
expected_end_of_object_bytes = cursor + message_length
|
||||
bytes_for_this_object = splittable[cursor:expected_end_of_object_bytes]
|
||||
try:
|
||||
message = message_class.from_bytes(bytes_for_this_object, **kwargs)
|
||||
except AttributeError:
|
||||
message = message_class(bytes_for_this_object, **kwargs)
|
||||
|
||||
message_objects.append(message)
|
||||
cursor = expected_end_of_object_bytes
|
||||
|
||||
remainder = splittable[cursor:]
|
||||
|
||||
if msgpack_remainder:
|
||||
message_objects.append(msgpack.loads(remainder))
|
||||
elif return_remainder:
|
||||
message_objects.append(remainder)
|
||||
|
||||
return message_objects
|
||||
|
||||
def __len__(self):
|
||||
return sum(self.get_message_meta(m)[1] for m in self.message_types)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_message_meta(message_type):
|
||||
try:
|
||||
message_class = message_type[0]
|
||||
except TypeError:
|
||||
message_class = message_type
|
||||
|
||||
try:
|
||||
# If a message length has been passed manually, it will be the second item.
|
||||
message_length = message_type[1]
|
||||
except TypeError:
|
||||
# If not, we expect it to be an attribute on the first item.
|
||||
message_length = message_class._EXPECTED_LENGTH
|
||||
except AttributeError:
|
||||
raise TypeError("No way to know the expected length. Either pass it as the second member of a tuple or set _EXPECTED_LENGTH on the class you're passing.")
|
||||
|
||||
try:
|
||||
kwargs = message_type[2]
|
||||
except (IndexError, TypeError):
|
||||
kwargs = {}
|
||||
|
||||
return message_class, message_length, kwargs
|
||||
|
||||
def __add__(self, splitter):
|
||||
return self.__class__(*self.message_types + splitter.message_types)
|
||||
|
||||
def __radd__(self, other):
|
||||
return other + bytes(self)
|
||||
|
||||
|
||||
class RepeatingBytestringSplitter(BytestringSplitter):
|
||||
|
||||
def __call__(self, splittable):
|
||||
remainder = True
|
||||
messages = []
|
||||
while remainder:
|
||||
message, remainder = super().__call__(splittable, return_remainder=True)
|
||||
messages.append(message)
|
||||
splittable = remainder
|
||||
return messages
|
||||
|
||||
|
||||
def fingerprint_from_key(public_key: Any):
|
||||
"""
|
||||
Hashes a key using keccak-256 and returns the hexdigest in bytes.
|
||||
|
|
|
@ -2,8 +2,7 @@ import requests
|
|||
from kademlia.node import Node
|
||||
|
||||
from nkms.crypto.constants import CFRAG_LENGTH
|
||||
from nkms.crypto.kits import MessageKit
|
||||
from nkms.crypto.utils import RepeatingBytestringSplitter
|
||||
from bytestring_splitter import RepeatingBytestringSplitter
|
||||
from nkms.network.capabilities import ServerCapability
|
||||
|
||||
from umbral.fragments import CapsuleFrag
|
||||
|
|
|
@ -6,7 +6,7 @@ from nkms.characters import Ursula
|
|||
from nkms.crypto.api import keccak_digest
|
||||
from nkms.crypto.constants import PUBLIC_KEY_LENGTH
|
||||
from nkms.crypto.powers import SigningPower, EncryptingPower
|
||||
from nkms.crypto.utils import BytestringSplitter
|
||||
from bytestring_splitter import BytestringSplitter
|
||||
from tests.utilities import MockNetworkyStuff
|
||||
from umbral.fragments import KFrag
|
||||
from umbral.keys import UmbralPublicKey
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
import pytest
|
||||
|
||||
from nkms.crypto import api
|
||||
from nkms.crypto.api import secure_random
|
||||
from nkms.crypto.constants import KFRAG_LENGTH
|
||||
from nkms.crypto.signature import Signature
|
||||
from nkms.crypto.utils import BytestringSplitter
|
||||
from umbral.bignum import BigNum
|
||||
from umbral.fragments import KFrag
|
||||
from umbral.point import Point
|
||||
from bytestring_splitter import BytestringSplitter
|
||||
|
||||
|
||||
def test_split_two_signatures():
|
||||
|
|
Loading…
Reference in New Issue