mirror of https://github.com/nucypher/nucypher.git
Merge pull request #775 from KPrasch/baby-carrots
Unicode Policy Labels - Conventional Character Control API Keyspull/778/head
commit
4404c7a3ac
|
@ -14,6 +14,7 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
import datetime
|
||||
import json
|
||||
import random
|
||||
from base64 import b64encode, b64decode
|
||||
|
@ -45,6 +46,8 @@ from bytestring_splitter import BytestringKwargifier, BytestringSplittingError
|
|||
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
|
||||
from constant_sorrow import constants, constant_or_bytes
|
||||
from constant_sorrow.constants import INCLUDED_IN_BYTESTRING, PUBLIC_ONLY
|
||||
|
||||
import nucypher
|
||||
from nucypher.blockchain.eth.actors import PolicyAuthor, Miner
|
||||
from nucypher.blockchain.eth.agents import MinerAgent
|
||||
from nucypher.characters.base import Character, Learner
|
||||
|
@ -217,10 +220,11 @@ class Alice(Character, PolicyAuthor):
|
|||
Character control endpoint for creating a policy and making
|
||||
arrangements with Ursulas.
|
||||
|
||||
This is an unfinished API endpoint. You are probably looking for grant.
|
||||
TODO: This is an unfinished API endpoint. You are probably looking for grant.
|
||||
TODO: Needs input cleansing and validation
|
||||
TODO: Provide more informative errors
|
||||
"""
|
||||
# TODO: Needs input cleansing and validation
|
||||
# TODO: Provide more informative errors
|
||||
|
||||
try:
|
||||
request_data = json.loads(request.data)
|
||||
|
||||
|
@ -238,28 +242,27 @@ class Alice(Character, PolicyAuthor):
|
|||
|
||||
new_policy = drone_alice.create_policy(bob, label, m, n,
|
||||
federated=federated_only)
|
||||
# TODO: Serialize the policy
|
||||
return Response('Policy created!', status=200)
|
||||
|
||||
@alice_control.route('/derive_policy_pubkey', methods=['POST'])
|
||||
def derive_policy_pubkey():
|
||||
response_data = {'result': {'label': new_policy.label.decode(),
|
||||
'policy_encrypting_key': new_policy.public_key.to_bytes().hex()},
|
||||
'version': str(nucypher.__version__)}
|
||||
|
||||
return Response(json.dumps(response_data), status=200)
|
||||
|
||||
@alice_control.route('/derive_policy_pubkey/<label>', methods=['POST'])
|
||||
def derive_policy_pubkey(label):
|
||||
"""
|
||||
Character control endpoint for deriving a policy pubkey given
|
||||
a label.
|
||||
"""
|
||||
try:
|
||||
request_data = json.loads(request.data)
|
||||
|
||||
label = b64decode(request_data['label'])
|
||||
except (KeyError, JSONDecodeError) as e:
|
||||
return Response(str(e), status=400)
|
||||
|
||||
policy_pubkey = drone_alice.get_policy_pubkey_from_label(label)
|
||||
label_bytes = label.encode()
|
||||
policy_pubkey = drone_alice.get_policy_pubkey_from_label(label_bytes)
|
||||
|
||||
response_data = {
|
||||
'result': {
|
||||
'policy_encrypting_pubkey': bytes(policy_pubkey).hex(),
|
||||
}
|
||||
'policy_encrypting_key': bytes(policy_pubkey).hex(),
|
||||
},
|
||||
'version': str(nucypher.__version__)
|
||||
}
|
||||
|
||||
return Response(json.dumps(response_data), status=200)
|
||||
|
@ -276,17 +279,21 @@ class Alice(Character, PolicyAuthor):
|
|||
|
||||
bob_pubkey_enc = bytes.fromhex(request_data['bob_encrypting_key'])
|
||||
bob_pubkey_sig = bytes.fromhex(request_data['bob_signing_key'])
|
||||
label = b64decode(request_data['label'])
|
||||
label = request_data['label'].encode()
|
||||
# TODO: Do we change this to something like "threshold"
|
||||
m, n = request_data['m'], request_data['n']
|
||||
expiration_time = maya.MayaDT.from_iso8601(
|
||||
request_data['expiration_time'])
|
||||
federated_only = True # const for now
|
||||
expiration = request_data.get("expiration_time")
|
||||
if expiration:
|
||||
expiration_time = maya.MayaDT.from_iso8601(
|
||||
request_data['expiration_time'])
|
||||
else:
|
||||
expiration_time = (maya.now() + datetime.timedelta(days=3))
|
||||
|
||||
bob = Bob.from_public_keys({DecryptingPower: bob_pubkey_enc,
|
||||
SigningPower: bob_pubkey_sig},
|
||||
federated_only=True)
|
||||
federated_only=True) # TODO: Const for now
|
||||
except (KeyError, JSONDecodeError) as e:
|
||||
print(e) # TODO: Make this a genuine log. Just for demos for now.
|
||||
return Response(str(e), status=400)
|
||||
|
||||
new_policy = drone_alice.grant(bob, label, m=m, n=n,
|
||||
|
@ -295,10 +302,11 @@ class Alice(Character, PolicyAuthor):
|
|||
response_data = {
|
||||
'result': {
|
||||
'treasure_map': b64encode(bytes(new_policy.treasure_map)).decode(),
|
||||
'policy_encrypting_pubkey': bytes(new_policy.public_key).hex(),
|
||||
'alice_signing_pubkey': bytes(new_policy.alice.stamp).hex(),
|
||||
'label': b64encode(new_policy.label).decode(),
|
||||
}
|
||||
'policy_encrypting_key': bytes(new_policy.public_key).hex(),
|
||||
'alice_signing_key': bytes(new_policy.alice.stamp).hex(),
|
||||
'label': new_policy.label.decode(),
|
||||
},
|
||||
'version': str(nucypher.__version__)
|
||||
}
|
||||
|
||||
return Response(json.dumps(response_data), status=200)
|
||||
|
@ -552,8 +560,8 @@ class Bob(Character):
|
|||
try:
|
||||
request_data = json.loads(request.data)
|
||||
|
||||
label = b64decode(request_data['label'])
|
||||
alice_pubkey_sig = bytes.fromhex(request_data['alice_signing_pubkey'])
|
||||
label = request_data['label'].encode()
|
||||
alice_pubkey_sig = bytes.fromhex(request_data['alice_signing_key'])
|
||||
except (KeyError, JSONDecodeError) as e:
|
||||
return Response(e, status=400)
|
||||
|
||||
|
@ -569,21 +577,21 @@ class Bob(Character):
|
|||
"""
|
||||
try:
|
||||
request_data = json.loads(request.data)
|
||||
|
||||
label = b64decode(request_data['label'])
|
||||
policy_pubkey_enc = bytes.fromhex(request_data['policy_encrypting_pubkey'])
|
||||
alice_pubkey_sig = bytes.fromhex(request_data['alice_signing_pubkey'])
|
||||
message_kit = b64decode(request_data['message_kit'])
|
||||
label = request_data['label'].encode()
|
||||
policy_pubkey_enc = bytes.fromhex(request_data['policy_encrypting_key'])
|
||||
alice_pubkey_sig = bytes.fromhex(request_data['alice_signing_key'])
|
||||
message_kit = b64decode(request_data['message_kit'].encode())
|
||||
except (KeyError, JSONDecodeError) as e:
|
||||
return Response(e, status=400)
|
||||
|
||||
policy_encrypting_key = UmbralPublicKey.from_bytes(policy_pubkey_enc)
|
||||
alice_pubkey_sig = UmbralPublicKey.from_bytes(alice_pubkey_sig)
|
||||
message_kit = UmbralMessageKit.from_bytes(message_kit)
|
||||
message_kit = UmbralMessageKit.from_bytes(message_kit) # TODO: May raise UnknownOpenSSLError and InvalidTag.
|
||||
|
||||
data_source = Enrico.from_public_keys({SigningPower: message_kit.sender_pubkey_sig},
|
||||
policy_encrypting_key=policy_encrypting_key,
|
||||
label=label)
|
||||
|
||||
drone_bob.join_policy(label=label, alice_pubkey_sig=alice_pubkey_sig)
|
||||
plaintexts = drone_bob.retrieve(message_kit=message_kit,
|
||||
data_source=data_source,
|
||||
|
@ -594,7 +602,8 @@ class Bob(Character):
|
|||
response_data = {
|
||||
'result': {
|
||||
'plaintext': plaintexts,
|
||||
}
|
||||
},
|
||||
'version': str(nucypher.__version__)
|
||||
}
|
||||
|
||||
return Response(json.dumps(response_data), status=200)
|
||||
|
@ -1132,18 +1141,19 @@ class Enrico(Character):
|
|||
"""
|
||||
try:
|
||||
request_data = json.loads(request.data)
|
||||
|
||||
message = b64decode(request_data['message'])
|
||||
message = request_data['message']
|
||||
except (KeyError, JSONDecodeError) as e:
|
||||
return Response(str(e), status=400)
|
||||
|
||||
message_kit, signature = drone_enrico.encrypt_message(message)
|
||||
# Encrypt
|
||||
message_kit, signature = drone_enrico.encrypt_message(bytes(message, encoding='utf-8'))
|
||||
|
||||
response_data = {
|
||||
'result': {
|
||||
'message_kit': b64encode(message_kit.to_bytes()).decode(),
|
||||
'message_kit': b64encode(message_kit.to_bytes()).decode(), # FIXME
|
||||
'signature': b64encode(bytes(signature)).decode(),
|
||||
}
|
||||
},
|
||||
'version': str(nucypher.__version__)
|
||||
}
|
||||
|
||||
return Response(json.dumps(response_data), status=200)
|
||||
|
|
|
@ -177,7 +177,7 @@ def alice(click_config,
|
|||
alice_control = ALICE.make_wsgi_app()
|
||||
click.secho("Starting Alice Character Control...")
|
||||
|
||||
click.secho(f"Alice Signing Key {bytes(ALICE.stamp).hex()}", fg="green", bold=True)
|
||||
click.secho(f"Alice Verifying Key {bytes(ALICE.stamp).hex()}", fg="green", bold=True)
|
||||
|
||||
# Run
|
||||
if dry_run:
|
||||
|
|
|
@ -170,7 +170,7 @@ def bob(click_config,
|
|||
bob_control = BOB.make_wsgi_app()
|
||||
click.secho("Starting Bob Character Control...")
|
||||
|
||||
click.secho(f"Bob Signing Key {bytes(BOB.stamp).hex()}", fg="green", bold=True)
|
||||
click.secho(f"Bob Verifying Key {bytes(BOB.stamp).hex()}", fg="green", bold=True)
|
||||
click.secho(f"Bob Encrypting Key {bytes(BOB.public_keys(DecryptingPower)).hex()}", fg="blue", bold=True)
|
||||
|
||||
# Run
|
||||
|
|
|
@ -36,7 +36,7 @@ def enrico(action, policy_encrypting_key, dry_run, http_port):
|
|||
enrico_control = ENRICO.make_wsgi_app()
|
||||
click.secho("Starting Enrico Character Control...")
|
||||
|
||||
click.secho(f"Enrico Signing Key {bytes(ENRICO.stamp).hex()}", fg="green", bold=True)
|
||||
click.secho(f"Enrico Verifying Key {bytes(ENRICO.stamp).hex()}", fg="green", bold=True)
|
||||
|
||||
# Run
|
||||
if dry_run:
|
||||
|
|
|
@ -15,9 +15,6 @@ from nucypher.network.middleware import RestMiddleware
|
|||
from nucypher.network.nodes import FleetStateTracker
|
||||
from nucypher.utilities.logging import SimpleObserver
|
||||
|
||||
|
||||
globalLogPublisher.addObserver(SimpleObserver())
|
||||
|
||||
MOE_BANNER = r"""
|
||||
_______
|
||||
| | |.-----..-----.
|
||||
|
|
|
@ -378,7 +378,7 @@ class NodeConfiguration(ABC):
|
|||
storage_type = storage_payload[NodeStorage._TYPE_LABEL]
|
||||
storage_class = node_storage_subclasses[storage_type]
|
||||
node_storage = storage_class.from_payload(payload=storage_payload,
|
||||
character_class=cls._CHARACTER_CLASS,
|
||||
# character_class=cls._CHARACTER_CLASS, # TODO: Do not pass this here - Always Use Ursula
|
||||
federated_only=payload['federated_only'],
|
||||
serializer=cls.NODE_SERIALIZER,
|
||||
deserializer=cls.NODE_DESERIALIZER)
|
||||
|
|
|
@ -39,6 +39,7 @@ class NotFound(UnexpectedResponse):
|
|||
|
||||
class NucypherMiddlewareClient:
|
||||
library = requests
|
||||
timeout = 1.2
|
||||
|
||||
@staticmethod
|
||||
def response_cleaner(response):
|
||||
|
@ -60,6 +61,9 @@ class NucypherMiddlewareClient:
|
|||
|
||||
def invoke_method(self, method, url, *args, **kwargs):
|
||||
self.clean_params(kwargs)
|
||||
if not kwargs.get("timeout"):
|
||||
if self.timeout:
|
||||
kwargs["timeout"] = self.timeout
|
||||
response = method(url, *args, **kwargs)
|
||||
return response
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ class GlobalConsoleLogger:
|
|||
cls.start()
|
||||
|
||||
|
||||
def logToSentry(cls, event):
|
||||
def logToSentry(event):
|
||||
|
||||
# Handle Logs...
|
||||
if not event.get('isError') or 'failure' not in event:
|
||||
|
|
|
@ -26,6 +26,8 @@ from constant_sorrow.constants import CERTIFICATE_NOT_SAVED
|
|||
|
||||
class _TestMiddlewareClient(NucypherMiddlewareClient):
|
||||
|
||||
timeout = None
|
||||
|
||||
@staticmethod
|
||||
def response_cleaner(response):
|
||||
response.content = response.data
|
||||
|
|
|
@ -14,10 +14,14 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import random
|
||||
from collections import OrderedDict
|
||||
from typing import Set
|
||||
|
||||
import maya
|
||||
from typing import Set
|
||||
|
||||
from nucypher.characters.lawful import Ursula
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
|
@ -76,3 +80,15 @@ class MockPolicyCreation:
|
|||
assert tx_hash == cls.tx_hash
|
||||
cls.waited_for_receipt = True
|
||||
|
||||
|
||||
def generate_random_label() -> bytes:
|
||||
"""
|
||||
Generates a random bytestring for use as a test label.
|
||||
:return: bytes
|
||||
"""
|
||||
adjs = ('my', 'sesame-street', 'black', 'cute')
|
||||
nouns = ('lizard', 'super-secret', 'data', 'coffee')
|
||||
combinations = list('-'.join((a, n)) for a in adjs for n in nouns)
|
||||
selection = random.choice(combinations)
|
||||
random_label = f'label://{selection}-{os.urandom(4).hex()}'
|
||||
return bytes(random_label, encoding='utf-8')
|
||||
|
|
|
@ -3,10 +3,14 @@ import json
|
|||
from base64 import b64encode, b64decode
|
||||
|
||||
import maya
|
||||
import pytest
|
||||
|
||||
import nucypher
|
||||
from nucypher.characters.lawful import Enrico
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.powers import DecryptingPower
|
||||
from nucypher.policy.models import TreasureMap
|
||||
from nucypher.utilities.sandbox.policy import generate_random_label
|
||||
|
||||
|
||||
def test_alice_character_control_create_policy(alice_control_test_client, federated_bob):
|
||||
|
@ -22,33 +26,28 @@ def test_alice_character_control_create_policy(alice_control_test_client, federa
|
|||
}
|
||||
response = alice_control_test_client.put('/create_policy', data=json.dumps(request_data))
|
||||
assert response.status_code == 200
|
||||
assert response.data == b'Policy created!'
|
||||
|
||||
create_policy_response = json.loads(response.data)
|
||||
assert 'version' in create_policy_response
|
||||
assert 'label' in create_policy_response['result']
|
||||
|
||||
try:
|
||||
bytes.fromhex(create_policy_response['result']['policy_encrypting_key'])
|
||||
except (KeyError, ValueError):
|
||||
pytest.fail("Invalid Policy Encrypting Key")
|
||||
|
||||
# Send bad data to assert error returns
|
||||
response = alice_control_test_client.put('/create_policy', data='bad')
|
||||
assert response.status_code == 400
|
||||
|
||||
del(request_data['bob_encrypting_key'])
|
||||
response = alice_control_test_client.put('/create_policy', data=json.dumps(request_data))
|
||||
|
||||
|
||||
def test_alice_character_control_derive_policy_pubkey(alice_control_test_client):
|
||||
request_data = {
|
||||
'label': b64encode(b'test').decode(),
|
||||
}
|
||||
response = alice_control_test_client.post('/derive_policy_pubkey', data=json.dumps(request_data))
|
||||
label = 'test'
|
||||
response = alice_control_test_client.post(f'/derive_policy_pubkey/{label}')
|
||||
assert response.status_code == 200
|
||||
|
||||
response_data = json.loads(response.data)
|
||||
assert 'policy_encrypting_pubkey' in response_data['result']
|
||||
|
||||
# Test bad data returns an error
|
||||
response = alice_control_test_client.post('/derive_policy_pubkey', data='bad')
|
||||
assert response.status_code == 400
|
||||
|
||||
del(request_data['label'])
|
||||
response = alice_control_test_client.post('/derive_policy_pubkey', data=request_data)
|
||||
assert response.status_code == 400
|
||||
assert 'policy_encrypting_key' in response_data['result']
|
||||
|
||||
|
||||
def test_alice_character_control_grant(alice_control_test_client, federated_bob):
|
||||
|
@ -57,7 +56,7 @@ def test_alice_character_control_grant(alice_control_test_client, federated_bob)
|
|||
request_data = {
|
||||
'bob_encrypting_key': bytes(bob_pubkey_enc).hex(),
|
||||
'bob_signing_key': bytes(federated_bob.stamp).hex(),
|
||||
'label': b64encode(bytes(b'test')).decode(),
|
||||
'label': 'test',
|
||||
'm': 2,
|
||||
'n': 3,
|
||||
'expiration_time': (maya.now() + datetime.timedelta(days=3)).iso8601(),
|
||||
|
@ -67,8 +66,8 @@ def test_alice_character_control_grant(alice_control_test_client, federated_bob)
|
|||
|
||||
response_data = json.loads(response.data)
|
||||
assert 'treasure_map' in response_data['result']
|
||||
assert 'policy_encrypting_pubkey' in response_data['result']
|
||||
assert 'alice_signing_pubkey' in response_data['result']
|
||||
assert 'policy_encrypting_key' in response_data['result']
|
||||
assert 'alice_signing_key' in response_data['result']
|
||||
assert 'label' in response_data['result']
|
||||
|
||||
map_bytes = b64decode(response_data['result']['treasure_map'])
|
||||
|
@ -85,8 +84,8 @@ def test_alice_character_control_grant(alice_control_test_client, federated_bob)
|
|||
|
||||
def test_bob_character_control_join_policy(bob_control_test_client, enacted_federated_policy):
|
||||
request_data = {
|
||||
'label': b64encode(enacted_federated_policy.label).decode(),
|
||||
'alice_signing_pubkey': bytes(enacted_federated_policy.alice.stamp).hex(),
|
||||
'label': enacted_federated_policy.label.decode(),
|
||||
'alice_signing_key': bytes(enacted_federated_policy.alice.stamp).hex(),
|
||||
}
|
||||
|
||||
# Simulate passing in a teacher-uri
|
||||
|
@ -100,19 +99,21 @@ def test_bob_character_control_join_policy(bob_control_test_client, enacted_fede
|
|||
response = bob_control_test_client.post('/join_policy', data='bad')
|
||||
assert response.status_code == 400
|
||||
|
||||
del(request_data['alice_signing_pubkey'])
|
||||
response = bob_control_test_client.put('/join_policy', data=json.dumps(request_data))
|
||||
# Missing Key results in bad request
|
||||
del(request_data['alice_signing_key'])
|
||||
response = bob_control_test_client.post('/join_policy', data=json.dumps(request_data))
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_bob_character_control_retrieve(bob_control_test_client, enacted_federated_policy, capsule_side_channel):
|
||||
message_kit, data_source = capsule_side_channel
|
||||
|
||||
request_data = {
|
||||
'label': b64encode(enacted_federated_policy.label).decode(),
|
||||
'policy_encrypting_pubkey': bytes(enacted_federated_policy.public_key).hex(),
|
||||
'alice_signing_pubkey': bytes(enacted_federated_policy.alice.stamp).hex(),
|
||||
'label': enacted_federated_policy.label.decode(),
|
||||
'policy_encrypting_key': bytes(enacted_federated_policy.public_key).hex(),
|
||||
'alice_signing_key': bytes(enacted_federated_policy.alice.stamp).hex(),
|
||||
'message_kit': b64encode(message_kit.to_bytes()).decode(),
|
||||
'datasource_signing_pubkey': bytes(data_source.stamp).hex(),
|
||||
'datasource_signing_key': bytes(data_source.stamp).hex(),
|
||||
}
|
||||
|
||||
response = bob_control_test_client.post('/retrieve', data=json.dumps(request_data))
|
||||
|
@ -128,7 +129,7 @@ def test_bob_character_control_retrieve(bob_control_test_client, enacted_federat
|
|||
response = bob_control_test_client.post('/retrieve', data='bad')
|
||||
assert response.status_code == 400
|
||||
|
||||
del(request_data['alice_signing_pubkey'])
|
||||
del(request_data['alice_signing_key'])
|
||||
response = bob_control_test_client.put('/retrieve', data=json.dumps(request_data))
|
||||
|
||||
|
||||
|
@ -145,8 +146,7 @@ def test_enrico_character_control_encrypt_message(enrico_control_test_client):
|
|||
assert 'signature' in response_data['result']
|
||||
|
||||
# Check that it serializes correctly.
|
||||
message_kit = UmbralMessageKit.from_bytes(
|
||||
b64decode(response_data['result']['message_kit']))
|
||||
message_kit = UmbralMessageKit.from_bytes(b64decode(response_data['result']['message_kit']))
|
||||
|
||||
# Send bad data to assert error return
|
||||
response = enrico_control_test_client.post('/encrypt_message', data='bad')
|
||||
|
@ -157,39 +157,50 @@ def test_enrico_character_control_encrypt_message(enrico_control_test_client):
|
|||
assert response.status_code == 400
|
||||
|
||||
|
||||
def test_character_control_lifecycle(alice_control_test_client, bob_control_test_client,
|
||||
def test_character_control_lifecycle(alice_control_test_client,
|
||||
bob_control_test_client,
|
||||
enrico_control_from_alice,
|
||||
federated_alice, federated_bob):
|
||||
federated_alice,
|
||||
federated_bob,
|
||||
federated_ursulas,
|
||||
random_policy_label):
|
||||
|
||||
random_label = random_policy_label.decode() # Unicode string
|
||||
|
||||
# Create a policy via Alice control
|
||||
alice_request_data = {
|
||||
'bob_encrypting_key': bytes(federated_bob.public_keys(DecryptingPower)).hex(),
|
||||
'label': b64encode(b'test').decode(),
|
||||
'bob_signing_key': bytes(federated_bob.stamp).hex(),
|
||||
'm': 2, 'n': 3,
|
||||
'expiration_time': (maya.now() + datetime.timedelta(days=3)).iso8601(),
|
||||
'bob_encrypting_key': bytes(federated_bob.public_keys(DecryptingPower)).hex(),
|
||||
'm': 1, 'n': 1,
|
||||
'label': random_label,
|
||||
# 'expiration_time': (maya.now() + datetime.timedelta(days=3)).iso8601(), # TODO
|
||||
}
|
||||
|
||||
response = alice_control_test_client.put('/grant', data=json.dumps(alice_request_data))
|
||||
assert response.status_code == 200
|
||||
|
||||
# Check Response Keys
|
||||
alice_response_data = json.loads(response.data)
|
||||
assert 'treasure_map' in alice_response_data['result']
|
||||
assert 'policy_encrypting_pubkey' in alice_response_data['result']
|
||||
assert 'alice_signing_pubkey' in alice_response_data['result']
|
||||
assert 'policy_encrypting_key' in alice_response_data['result']
|
||||
assert 'alice_signing_key' in alice_response_data['result']
|
||||
assert 'label' in alice_response_data['result']
|
||||
assert 'version' in alice_response_data
|
||||
assert str(nucypher.__version__) == alice_response_data['version']
|
||||
|
||||
# This is sidechannel policy metadata. It should be given to Bob by the
|
||||
# application developer at some point.
|
||||
policy_pubkey_enc_hex = alice_response_data['result']['policy_encrypting_pubkey']
|
||||
alice_pubkey_sig_hex = alice_response_data['result']['alice_signing_pubkey']
|
||||
label = b64decode(alice_response_data['result']['label'])
|
||||
policy_pubkey_enc_hex = alice_response_data['result']['policy_encrypting_key']
|
||||
alice_pubkey_sig_hex = alice_response_data['result']['alice_signing_key']
|
||||
label = alice_response_data['result']['label']
|
||||
|
||||
# Encrypt some data via Enrico control
|
||||
# Alice will also be Enrico via Enrico.from_alice
|
||||
# (see enrico_control_from_alice fixture)
|
||||
|
||||
enrico_encoded_message = "I'm bereaved, not a sap!" # type: str
|
||||
enrico_request_data = {
|
||||
'message': b64encode(b"I'm bereaved, not a sap!").decode(),
|
||||
'message': enrico_encoded_message,
|
||||
}
|
||||
|
||||
response = enrico_control_from_alice.post('/encrypt_message', data=json.dumps(enrico_request_data))
|
||||
|
@ -199,17 +210,23 @@ def test_character_control_lifecycle(alice_control_test_client, bob_control_test
|
|||
assert 'message_kit' in enrico_response_data['result']
|
||||
assert 'signature' in enrico_response_data['result']
|
||||
|
||||
kit_bytes = b64decode(enrico_response_data['result']['message_kit'])
|
||||
kit_bytes = b64decode(enrico_response_data['result']['message_kit'].encode())
|
||||
bob_message_kit = UmbralMessageKit.from_bytes(kit_bytes)
|
||||
|
||||
# Retrieve data via Bob control
|
||||
encoded_message_kit = b64encode(bob_message_kit.to_bytes()).decode()
|
||||
|
||||
bob_request_data = {
|
||||
'label': b64encode(label).decode(),
|
||||
'policy_encrypting_pubkey': policy_pubkey_enc_hex,
|
||||
'alice_signing_pubkey': alice_pubkey_sig_hex,
|
||||
'message_kit': b64encode(bob_message_kit.to_bytes()).decode(),
|
||||
'label': label,
|
||||
'policy_encrypting_key': policy_pubkey_enc_hex,
|
||||
'alice_signing_key': alice_pubkey_sig_hex,
|
||||
'message_kit': encoded_message_kit,
|
||||
}
|
||||
|
||||
# Give bob a node to remember
|
||||
teacher = list(federated_ursulas)[1]
|
||||
federated_bob.remember_node(teacher)
|
||||
|
||||
response = bob_control_test_client.post('/retrieve', data=json.dumps(bob_request_data))
|
||||
assert response.status_code == 200
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
import pytest
|
||||
from bytestring_splitter import BytestringSplitter, BytestringSplittingError
|
||||
|
||||
from nucypher.characters.lawful import Enrico
|
||||
from nucypher.crypto.api import secure_random
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.signing import Signature
|
||||
|
||||
|
||||
|
@ -51,3 +53,26 @@ def test_trying_to_extract_too_many_bytes_raises_typeerror():
|
|||
|
||||
with pytest.raises(BytestringSplittingError):
|
||||
rebuilt_signature, rebuilt_bytes = splitter(signature + some_bytes, return_remainder=True)
|
||||
|
||||
|
||||
def test_message_kit_serialization_via_enrico(enacted_federated_policy, federated_alice):
|
||||
|
||||
# Enrico
|
||||
enrico = Enrico.from_alice(federated_alice, label=enacted_federated_policy.label)
|
||||
|
||||
# Plaintext
|
||||
message = 'this is a message'
|
||||
plaintext_bytes = bytes(message, encoding='utf-8')
|
||||
|
||||
# Create
|
||||
message_kit, signature = enrico.encrypt_message(message=plaintext_bytes)
|
||||
|
||||
# Serialize
|
||||
message_kit_bytes = message_kit.to_bytes()
|
||||
|
||||
# Deserialize
|
||||
the_same_message_kit = UmbralMessageKit.from_bytes(message_kit_bytes)
|
||||
|
||||
# Confirm
|
||||
assert message_kit_bytes == the_same_message_kit.to_bytes()
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
import datetime
|
||||
import os
|
||||
import random
|
||||
import tempfile
|
||||
|
||||
import maya
|
||||
|
@ -40,6 +41,7 @@ from nucypher.utilities.sandbox.constants import (NUMBER_OF_URSULAS_IN_DEVELOPME
|
|||
DEVELOPMENT_TOKEN_AIRDROP_AMOUNT, MOCK_URSULA_STARTING_PORT,
|
||||
MOCK_POLICY_DEFAULT_M)
|
||||
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
||||
from nucypher.utilities.sandbox.policy import generate_random_label
|
||||
from nucypher.utilities.sandbox.ursula import make_federated_ursulas, make_decentralized_ursulas
|
||||
|
||||
TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts')
|
||||
|
@ -207,7 +209,7 @@ def idle_federated_policy(federated_alice, federated_bob):
|
|||
"""
|
||||
m = MOCK_POLICY_DEFAULT_M
|
||||
n = NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK
|
||||
random_label = b'label://' + os.urandom(32)
|
||||
random_label = generate_random_label()
|
||||
policy = federated_alice.create_policy(federated_bob, label=random_label, m=m, n=n, federated=True)
|
||||
return policy
|
||||
|
||||
|
@ -235,7 +237,7 @@ def idle_blockchain_policy(blockchain_alice, blockchain_bob):
|
|||
"""
|
||||
Creates a Policy, in a manner typical of how Alice might do it, with a unique label
|
||||
"""
|
||||
random_label = b'label://' + os.urandom(32)
|
||||
random_label = generate_random_label()
|
||||
policy = blockchain_alice.create_policy(blockchain_bob, label=random_label, m=2, n=3)
|
||||
return policy
|
||||
|
||||
|
@ -263,6 +265,11 @@ def capsule_side_channel(enacted_federated_policy):
|
|||
return message_kit, enrico
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def random_policy_label():
|
||||
yield generate_random_label()
|
||||
|
||||
|
||||
#
|
||||
# Alice, Bob, and Ursula
|
||||
#
|
||||
|
@ -347,8 +354,8 @@ def enrico_control_test_client(capsule_side_channel):
|
|||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def enrico_control_from_alice(federated_alice):
|
||||
enrico = Enrico.from_alice(federated_alice, b'test')
|
||||
def enrico_control_from_alice(federated_alice, random_policy_label):
|
||||
enrico = Enrico.from_alice(federated_alice, random_policy_label)
|
||||
|
||||
enrico_control = enrico.make_wsgi_app()
|
||||
enrico_control.config['DEBUG'] = True
|
||||
|
|
Loading…
Reference in New Issue