mirror of https://github.com/nucypher/nucypher.git
Minimal fixes to make CI pass, using an adapter for Umbral
parent
71af0f062b
commit
e6fcdbbff6
|
@ -24,7 +24,7 @@ import msgpack
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.characters.lawful import Bob, Enrico, Ursula
|
||||
from nucypher.config.constants import TEMPORARY_DOMAIN
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
import json
|
||||
import os
|
||||
from umbral.keys import UmbralPrivateKey, UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, UmbralPublicKey
|
||||
|
||||
DOCTOR_PUBLIC_JSON = 'doctor.public.json'
|
||||
DOCTOR_PRIVATE_JSON = 'doctor.private.json'
|
||||
|
|
|
@ -24,10 +24,3 @@ from nucypher.__about__ import (
|
|||
__all__ = [
|
||||
"__title__", "__summary__", "__version__", "__author__", "__license__", "__copyright__", "__email__", "__url__"
|
||||
]
|
||||
|
||||
|
||||
# Set Default Curve #
|
||||
#####################
|
||||
|
||||
from umbral.config import set_default_curve
|
||||
set_default_curve()
|
||||
|
|
|
@ -34,8 +34,7 @@ from cryptography.exceptions import InvalidSignature
|
|||
from eth_keys import KeyAPI as EthKeyAPI
|
||||
from eth_utils import to_canonical_address, to_checksum_address
|
||||
from typing import ClassVar, Dict, List, Optional, Union
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.signing import Signature
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey, Signature
|
||||
|
||||
from nucypher.acumen.nicknames import Nickname
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||
|
@ -56,8 +55,8 @@ from nucypher.crypto.powers import (
|
|||
from nucypher.crypto.signing import (
|
||||
SignatureStamp,
|
||||
StrangerStamp,
|
||||
signature_splitter
|
||||
)
|
||||
from nucypher.crypto.splitters import signature_splitter
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
from nucypher.network.nodes import Learner
|
||||
|
||||
|
@ -505,9 +504,7 @@ class Character(Learner):
|
|||
def derive_federated_address(self):
|
||||
if self.federated_only:
|
||||
verifying_key = self.public_keys(SigningPower)
|
||||
uncompressed_bytes = verifying_key.to_bytes(is_compressed=False)
|
||||
without_prefix = uncompressed_bytes[1:]
|
||||
verifying_key_as_eth_key = EthKeyAPI.PublicKey(without_prefix)
|
||||
verifying_key_as_eth_key = EthKeyAPI.PublicKey.from_compressed_bytes(bytes(verifying_key))
|
||||
federated_address = verifying_key_as_eth_key.to_checksum_address()
|
||||
else:
|
||||
raise RuntimeError('Federated address can only be derived for federated characters.')
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
import functools
|
||||
import maya
|
||||
from typing import Union
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.characters.control.specifications import alice, bob, enrico
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"""
|
||||
|
||||
from marshmallow import fields
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.characters.control.specifications.exceptions import InvalidInputData, InvalidNativeDataTypes
|
||||
from nucypher.characters.control.specifications.fields.base import BaseField
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
from base64 import b64decode, b64encode
|
||||
|
||||
from marshmallow import fields
|
||||
from umbral.signing import Signature
|
||||
from nucypher.crypto.umbral_adapter import Signature
|
||||
|
||||
from nucypher.characters.control.specifications.exceptions import InvalidInputData, InvalidNativeDataTypes
|
||||
from nucypher.characters.control.specifications.fields.base import BaseField
|
||||
|
|
|
@ -25,6 +25,7 @@ from nucypher.characters.control.specifications.fields.base import BaseField
|
|||
from nucypher.crypto.constants import HRAC_LENGTH
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.signing import Signature
|
||||
from nucypher.crypto.splitters import signature_splitter
|
||||
|
||||
|
||||
class TreasureMap(BaseField, fields.Field):
|
||||
|
@ -40,7 +41,7 @@ class TreasureMap(BaseField, fields.Field):
|
|||
|
||||
def _validate(self, value):
|
||||
|
||||
splitter = BytestringSplitter(Signature,
|
||||
splitter = BytestringSplitter(signature_splitter,
|
||||
(bytes, HRAC_LENGTH), # hrac
|
||||
(UmbralMessageKit, VariableLengthBytestring)
|
||||
) # TODO: USe the one from TMap
|
||||
|
|
|
@ -56,10 +56,7 @@ from twisted.internet.defer import Deferred
|
|||
from twisted.internet.task import LoopingCall
|
||||
from twisted.logger import Logger
|
||||
from typing import Dict, Iterable, List, NamedTuple, Tuple, Union, Optional, Sequence, Set, Any
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.kfrags import KFrag
|
||||
from umbral.signing import Signature
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey, VerifiedKeyFrag, Signature, pre, VerificationError
|
||||
|
||||
import nucypher
|
||||
from nucypher.acumen.nicknames import Nickname
|
||||
|
@ -79,7 +76,7 @@ from nucypher.cli.processes import UrsulaCommandProtocol
|
|||
from nucypher.config.constants import END_OF_POLICIES_PROBATIONARY_PERIOD
|
||||
from nucypher.config.storages import ForgetfulNodeStorage, NodeStorage
|
||||
from nucypher.crypto.api import encrypt_and_sign, keccak_digest
|
||||
from nucypher.crypto.constants import HRAC_LENGTH, PUBLIC_KEY_LENGTH
|
||||
from nucypher.crypto.constants import HRAC_LENGTH
|
||||
from nucypher.crypto.keypairs import HostingKeypair
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.powers import (
|
||||
|
@ -90,6 +87,7 @@ from nucypher.crypto.powers import (
|
|||
TransactingPower
|
||||
)
|
||||
from nucypher.crypto.signing import InvalidSignature
|
||||
from nucypher.crypto.splitters import key_splitter, signature_splitter
|
||||
from nucypher.datastore.datastore import DatastoreTransactionError, RecordNotFound
|
||||
from nucypher.datastore.queries import find_expired_policies, find_expired_treasure_maps
|
||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||
|
@ -808,16 +806,22 @@ class Bob(Character):
|
|||
self._completed_work_orders.save_work_order(work_order, as_replete=retain_cfrags)
|
||||
|
||||
the_airing_of_grievances = []
|
||||
verified_cfrags = []
|
||||
for capsule, pre_task in work_order.tasks.items():
|
||||
if not pre_task.cfrag.verify_correctness(capsule):
|
||||
try:
|
||||
verified_cfrag = pre_task.cfrag.verify_correctness(capsule)
|
||||
except VerificationError:
|
||||
# TODO: WARNING - This block is untested.
|
||||
# I got a lot of problems with you people ...
|
||||
the_airing_of_grievances.append(work_order.ursula)
|
||||
else:
|
||||
verified_cfrags.append(verified_cfrag) # FIXME: this is unused
|
||||
pre_task.cfrag = verified_cfrag # FIXME: massive yikes, needs to be done properly
|
||||
|
||||
if the_airing_of_grievances:
|
||||
return False, the_airing_of_grievances
|
||||
else:
|
||||
return True, cfrags
|
||||
return True, verified_cfrags
|
||||
|
||||
def retrieve(self,
|
||||
|
||||
|
@ -1568,13 +1572,13 @@ class Ursula(Teacher, Character, Worker):
|
|||
public_address=ETH_ADDRESS_BYTE_LENGTH,
|
||||
domain=VariableLengthBytestring,
|
||||
timestamp=(int, 4, {'byteorder': 'big'}),
|
||||
interface_signature=Signature,
|
||||
interface_signature=signature_splitter,
|
||||
|
||||
# FIXME: Fixed length doesn't work with federated. It was LENGTH_ECDSA_SIGNATURE_WITH_RECOVERY,
|
||||
decentralized_identity_evidence=VariableLengthBytestring,
|
||||
|
||||
verifying_key=(UmbralPublicKey, PUBLIC_KEY_LENGTH),
|
||||
encrypting_key=(UmbralPublicKey, PUBLIC_KEY_LENGTH),
|
||||
verifying_key=key_splitter,
|
||||
encrypting_key=key_splitter,
|
||||
certificate=(load_pem_x509_certificate, VariableLengthBytestring, {"backend": default_backend()}),
|
||||
rest_interface=InterfaceInfo,
|
||||
)
|
||||
|
@ -1727,26 +1731,24 @@ class Ursula(Teacher, Character, Worker):
|
|||
# Re-Encryption
|
||||
#
|
||||
|
||||
def _reencrypt(self, kfrag: KFrag, work_order: 'WorkOrder', alice_verifying_key: UmbralPublicKey):
|
||||
def _reencrypt(self, kfrag: VerifiedKeyFrag, work_order: 'WorkOrder', alice_verifying_key: UmbralPublicKey):
|
||||
|
||||
# Prepare a bytestring for concatenating re-encrypted
|
||||
# capsule data for each work order task.
|
||||
cfrag_byte_stream = bytes()
|
||||
for capsule, task in work_order.tasks.items():
|
||||
# Ursula signs on top of Bob's signature of each task.
|
||||
# Now both are committed to the same task. See #259.
|
||||
reencryption_metadata = bytes(self.stamp(bytes(task.signature)))
|
||||
# See #259 for the discussion leading to the current protocol.
|
||||
|
||||
# Ursula sets Alice's verifying key for capsule correctness verification.
|
||||
capsule.set_correctness_keys(verifying=alice_verifying_key)
|
||||
|
||||
# Then re-encrypts the fragment.
|
||||
cfrag = pre.reencrypt(kfrag, capsule, metadata=reencryption_metadata) # <--- pyUmbral
|
||||
cfrag = pre.reencrypt(kfrag, capsule) # <--- pyUmbral
|
||||
self.log.info(f"Re-encrypted capsule {capsule} -> made {cfrag}.")
|
||||
|
||||
# Next, Ursula signs to commit to her results.
|
||||
reencryption_signature = self.stamp(bytes(cfrag))
|
||||
cfrag_byte_stream += VariableLengthBytestring(cfrag) + reencryption_signature
|
||||
cfrag_byte_stream += bytes(cfrag) + bytes(reencryption_signature)
|
||||
|
||||
# ... and finally returns all the re-encrypted bytes
|
||||
return cfrag_byte_stream
|
||||
|
|
|
@ -17,7 +17,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
import click
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.characters.control.interfaces import EnricoInterface
|
||||
from nucypher.characters.lawful import Enrico
|
||||
|
|
|
@ -20,7 +20,7 @@ from cryptography.exceptions import InternalError
|
|||
from decimal import Decimal, DecimalException
|
||||
from eth_utils import to_checksum_address
|
||||
from ipaddress import ip_address
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.blockchain.economics import StandardTokenEconomics
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
|
|
|
@ -34,7 +34,6 @@ from constant_sorrow.constants import (
|
|||
LIVE_CONFIGURATION
|
||||
)
|
||||
from eth_utils.address import is_checksum_address
|
||||
from umbral.signing import Signature
|
||||
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||
from nucypher.blockchain.eth.networks import NetworksInventory
|
||||
|
@ -53,6 +52,7 @@ from nucypher.config.storages import (
|
|||
NodeStorage
|
||||
)
|
||||
from nucypher.crypto.powers import CryptoPower, CryptoPowerUp
|
||||
from nucypher.crypto.umbral_adapter import Signature
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
from nucypher.utilities.logging import Logger
|
||||
|
||||
|
|
|
@ -33,20 +33,17 @@ from cryptography.hazmat.backends.openssl.ec import _EllipticCurvePrivateKey
|
|||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
|
||||
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
||||
from cryptography.hazmat.primitives.serialization import Encoding, load_pem_private_key
|
||||
from cryptography.x509 import Certificate
|
||||
from eth_account import Account
|
||||
from eth_keys import KeyAPI as EthKeyAPI
|
||||
from eth_utils import to_checksum_address
|
||||
from nacl.exceptions import CryptoError
|
||||
from nacl.secret import SecretBox
|
||||
from umbral.keys import UmbralKeyingMaterial, UmbralPrivateKey, UmbralPublicKey, derive_key_from_password
|
||||
from nucypher.crypto.umbral_adapter import UmbralKeyingMaterial, UmbralPrivateKey, UmbralPublicKey, derive_key_from_password, AuthenticationFailed
|
||||
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
|
||||
from nucypher.crypto.api import generate_teacher_certificate, _TLS_CURVE
|
||||
from nucypher.crypto.constants import BLAKE2B
|
||||
from nucypher.crypto.keypairs import HostingKeypair
|
||||
from nucypher.crypto.passwords import derive_wrapping_key_from_key_material, SecretBox
|
||||
from nucypher.crypto.powers import (DecryptingPower, DerivedKeyBasedPower, KeyPairBasedPower, SigningPower)
|
||||
from nucypher.network.server import TLSHostingPower
|
||||
from nucypher.utilities.logging import Logger
|
||||
|
@ -411,11 +408,11 @@ class NucypherKeyring:
|
|||
def __decrypt_keyfile(self, key_path: str) -> UmbralPrivateKey:
|
||||
"""Returns plaintext version of decrypting key."""
|
||||
key_data = _read_keyfile(key_path, deserializer=_deserialize_private_key)
|
||||
wrap_key = _derive_wrapping_key_from_key_material(salt=key_data['wrap_salt'],
|
||||
key_material=self.__derived_key_material)
|
||||
wrap_key = derive_wrapping_key_from_key_material(salt=key_data['wrap_salt'],
|
||||
key_material=self.__derived_key_material)
|
||||
try:
|
||||
plain_umbral_key = UmbralPrivateKey.from_bytes(key_bytes=key_data['key'], wrapping_key=wrap_key)
|
||||
except CryptoError:
|
||||
except AuthenticationFailed:
|
||||
raise self.AuthenticationFailed('Invalid or incorrect nucypher keyring password.')
|
||||
return plain_umbral_key
|
||||
|
||||
|
@ -440,14 +437,9 @@ class NucypherKeyring:
|
|||
return self.is_unlocked
|
||||
key_data = _read_keyfile(keypath=self.__root_keypath, deserializer=_deserialize_private_key)
|
||||
self.log.info("Unlocking keyring.")
|
||||
try:
|
||||
derived_key = derive_key_from_password(password=password.encode(), salt=key_data['master_salt'])
|
||||
except CryptoError:
|
||||
self.log.info("Keyring unlock failed.")
|
||||
raise self.AuthenticationFailed
|
||||
else:
|
||||
self.__derived_key_material = derived_key
|
||||
self.log.info("Finished unlocking.")
|
||||
derived_key = derive_key_from_password(password=password.encode(), salt=key_data['master_salt'])
|
||||
self.__derived_key_material = derived_key
|
||||
self.log.info("Finished unlocking.")
|
||||
return self.is_unlocked
|
||||
|
||||
@unlock_required
|
||||
|
@ -490,7 +482,7 @@ class NucypherKeyring:
|
|||
# Derived
|
||||
elif issubclass(power_class, DerivedKeyBasedPower):
|
||||
key_data = _read_keyfile(self.__delegating_keypath, deserializer=_deserialize_private_key)
|
||||
wrap_key = _derive_wrapping_key_from_key_material(salt=key_data['wrap_salt'], key_material=self.__derived_key_material)
|
||||
wrap_key = derive_wrapping_key_from_key_material(salt=key_data['wrap_salt'], key_material=self.__derived_key_material)
|
||||
keying_material = SecretBox(wrap_key).decrypt(key_data['key'])
|
||||
new_cryptopower = power_class(keying_material=keying_material)
|
||||
|
||||
|
@ -551,9 +543,7 @@ class NucypherKeyring:
|
|||
signing_private_key, signing_public_key = _generate_signing_keys()
|
||||
|
||||
if checksum_address is FEDERATED_ADDRESS:
|
||||
uncompressed_bytes = signing_public_key.to_bytes(is_compressed=False)
|
||||
without_prefix = uncompressed_bytes[1:]
|
||||
verifying_key_as_eth_key = EthKeyAPI.PublicKey(without_prefix)
|
||||
verifying_key_as_eth_key = EthKeyAPI.PublicKey.from_compressed_bytes(bytes(signing_public_key))
|
||||
checksum_address = verifying_key_as_eth_key.to_checksum_address()
|
||||
|
||||
else:
|
||||
|
@ -576,9 +566,9 @@ class NucypherKeyring:
|
|||
|
||||
cls.log.info("About to derive key from password.")
|
||||
derived_key_material = derive_key_from_password(salt=password_salt, password=password.encode())
|
||||
encrypting_wrap_key = _derive_wrapping_key_from_key_material(salt=encrypting_salt, key_material=derived_key_material)
|
||||
signature_wrap_key = _derive_wrapping_key_from_key_material(salt=signing_salt, key_material=derived_key_material)
|
||||
delegating_wrap_key = _derive_wrapping_key_from_key_material(salt=delegating_salt, key_material=derived_key_material)
|
||||
encrypting_wrap_key = derive_wrapping_key_from_key_material(salt=encrypting_salt, key_material=derived_key_material)
|
||||
signature_wrap_key = derive_wrapping_key_from_key_material(salt=signing_salt, key_material=derived_key_material)
|
||||
delegating_wrap_key = derive_wrapping_key_from_key_material(salt=delegating_salt, key_material=derived_key_material)
|
||||
|
||||
# Encapsulate Private Keys
|
||||
encrypting_key_data = encrypting_private_key.to_bytes(wrapping_key=encrypting_wrap_key)
|
||||
|
|
|
@ -35,9 +35,7 @@ from eth_utils import is_checksum_address, to_checksum_address
|
|||
from ipaddress import IPv4Address
|
||||
from random import SystemRandom
|
||||
from typing import Tuple
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralPrivateKey, UmbralPublicKey
|
||||
from umbral.signing import Signature
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, UmbralPublicKey, Signature, pre
|
||||
|
||||
from nucypher.crypto.constants import SHA256
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
|
@ -245,7 +243,7 @@ def encrypt_and_sign(recipient_pubkey_enc: UmbralPublicKey,
|
|||
# Sign first, encrypt second.
|
||||
sig_header = constants.SIGNATURE_TO_FOLLOW
|
||||
signature = signer(plaintext)
|
||||
ciphertext, capsule = pre.encrypt(recipient_pubkey_enc, sig_header + signature + plaintext)
|
||||
ciphertext, capsule = pre.encrypt(recipient_pubkey_enc, sig_header + bytes(signature) + plaintext)
|
||||
else:
|
||||
# Encrypt first, sign second.
|
||||
sig_header = constants.SIGNATURE_IS_ON_CIPHERTEXT
|
||||
|
|
|
@ -27,7 +27,3 @@ BLAKE2B_DIGEST_LENGTH = 64
|
|||
# Hashes
|
||||
SHA256 = hashes.SHA256()
|
||||
BLAKE2B = hashes.BLAKE2b(64)
|
||||
|
||||
# SECP256K1
|
||||
CAPSULE_LENGTH = 98
|
||||
PUBLIC_KEY_LENGTH = 33
|
||||
|
|
|
@ -24,9 +24,7 @@ from constant_sorrow import constants
|
|||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
from hendrix.deploy.tls import HendrixDeployTLS
|
||||
from hendrix.facilities.services import ExistingKeyTLSContextFactory
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralPrivateKey, UmbralPublicKey
|
||||
from umbral.signing import Signature, Signer
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, UmbralPublicKey, Signature, Signer, pre
|
||||
|
||||
from nucypher.config.constants import MAX_UPLOAD_CONTENT_LENGTH
|
||||
from nucypher.crypto import api as API
|
||||
|
@ -67,16 +65,14 @@ class Keypair(object):
|
|||
raise ValueError(
|
||||
"Either pass a valid key or, if you want to generate keys, set generate_keys_if_needed to True.")
|
||||
|
||||
def serialize_pubkey(self, as_b64=False) -> bytes:
|
||||
def serialize_pubkey(self) -> bytes:
|
||||
"""
|
||||
Serializes the pubkey for storage/transport in either urlsafe base64
|
||||
or as a bytestring.
|
||||
|
||||
:param as_b64: Return the pubkey as urlsafe base64 byte string
|
||||
:return: The serialized pubkey in bytes
|
||||
"""
|
||||
encoder = base64.urlsafe_b64encode if as_b64 else None
|
||||
return self.pubkey.to_bytes(encoder=encoder)
|
||||
return self.pubkey.to_bytes()
|
||||
|
||||
def fingerprint(self):
|
||||
"""
|
||||
|
|
|
@ -19,7 +19,7 @@ from typing import Optional
|
|||
|
||||
from bytestring_splitter import BytestringKwargifier, VariableLengthBytestring
|
||||
from constant_sorrow.constants import NOT_SIGNED, UNKNOWN_SENDER
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.crypto.splitters import capsule_splitter, key_splitter
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ import inspect
|
|||
from eth_typing.evm import ChecksumAddress
|
||||
from hexbytes import HexBytes
|
||||
from typing import List, Optional, Tuple
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralKeyingMaterial, UmbralPrivateKey, UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import pre, UmbralKeyingMaterial, UmbralPrivateKey, UmbralPublicKey
|
||||
|
||||
from nucypher.blockchain.eth.decorators import validate_checksum_address
|
||||
from nucypher.blockchain.eth.signers.base import Signer
|
||||
|
|
|
@ -17,12 +17,10 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
from bytestring_splitter import BytestringSplitter
|
||||
from umbral.signing import Signature, Signer
|
||||
from nucypher.crypto.umbral_adapter import Signature, Signer
|
||||
|
||||
from nucypher.crypto.api import keccak_digest
|
||||
|
||||
signature_splitter = BytestringSplitter(Signature)
|
||||
|
||||
|
||||
class SignatureStamp(object):
|
||||
"""
|
||||
|
|
|
@ -17,13 +17,9 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
|
||||
from umbral.cfrags import CapsuleFrag
|
||||
from umbral.config import default_params
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.pre import Capsule
|
||||
from nucypher.crypto.umbral_adapter import CapsuleFrag, UmbralPublicKey, Capsule, Signature
|
||||
|
||||
from nucypher.crypto.constants import CAPSULE_LENGTH, PUBLIC_KEY_LENGTH
|
||||
|
||||
key_splitter = BytestringSplitter((UmbralPublicKey, PUBLIC_KEY_LENGTH))
|
||||
capsule_splitter = BytestringSplitter((Capsule, CAPSULE_LENGTH, {"params": default_params()}))
|
||||
cfrag_splitter = BytestringSplitter((CapsuleFrag, VariableLengthBytestring))
|
||||
key_splitter = BytestringSplitter((UmbralPublicKey, UmbralPublicKey.serialized_size()))
|
||||
capsule_splitter = BytestringSplitter((Capsule, Capsule.serialized_size()))
|
||||
cfrag_splitter = BytestringSplitter((CapsuleFrag, CapsuleFrag.serialized_size()))
|
||||
signature_splitter = BytestringSplitter((Signature, Signature.serialized_size()))
|
||||
|
|
|
@ -239,12 +239,11 @@ class CapsuleFrag(umbral.CapsuleFrag):
|
|||
def to_bytes(self):
|
||||
return bytes(self)
|
||||
|
||||
def verify_correctness(self, capsule, metadata=None):
|
||||
def verify_correctness(self, capsule):
|
||||
keys = capsule.get_correctness_keys()
|
||||
return self.verify(
|
||||
capsule._capsule,
|
||||
verifying_pk=keys['verifying'], delegating_pk=keys['delegating'], receiving_pk=keys['receiving'],
|
||||
metadata=metadata)
|
||||
verifying_pk=keys['verifying'], delegating_pk=keys['delegating'], receiving_pk=keys['receiving'])
|
||||
|
||||
|
||||
# Adapter for standalone functions
|
||||
|
@ -253,9 +252,9 @@ class PRE:
|
|||
GenericUmbralError = umbral.GenericError
|
||||
|
||||
@staticmethod
|
||||
def reencrypt(kfrag, capsule, metadata=None):
|
||||
def reencrypt(kfrag, capsule):
|
||||
assert isinstance(capsule, Capsule)
|
||||
cf = umbral.reencrypt(capsule._capsule, kfrag, metadata=metadata)
|
||||
cf = umbral.reencrypt(capsule._capsule, kfrag)
|
||||
return cf
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -18,7 +18,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
from coincurve import PublicKey
|
||||
from eth_keys import KeyAPI as EthKeyAPI
|
||||
from typing import Any, Union
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.crypto.api import keccak_digest
|
||||
from nucypher.crypto.signing import SignatureStamp
|
||||
|
@ -43,7 +43,7 @@ def construct_policy_id(label: bytes, stamp: bytes) -> bytes:
|
|||
def canonical_address_from_umbral_key(public_key: Union[UmbralPublicKey, SignatureStamp]) -> bytes:
|
||||
if isinstance(public_key, SignatureStamp):
|
||||
public_key = public_key.as_umbral_pubkey()
|
||||
pubkey_compressed_bytes = public_key.to_bytes(is_compressed=True)
|
||||
pubkey_compressed_bytes = bytes(public_key)
|
||||
eth_pubkey = EthKeyAPI.PublicKey.from_compressed_bytes(pubkey_compressed_bytes)
|
||||
canonical_address = eth_pubkey.to_canonical_address()
|
||||
return canonical_address
|
||||
|
|
|
@ -15,8 +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 maya import MayaDT
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.kfrags import KFrag
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey, VerifiedKeyFrag
|
||||
|
||||
from nucypher.crypto.signing import Signature
|
||||
from nucypher.datastore.base import DatastoreRecord, RecordField
|
||||
|
@ -29,9 +28,9 @@ class PolicyArrangement(DatastoreRecord):
|
|||
encode=lambda maya_date: maya_date.iso8601().encode(),
|
||||
decode=lambda maya_bytes: MayaDT.from_iso8601(maya_bytes.decode()))
|
||||
_kfrag = RecordField(
|
||||
KFrag,
|
||||
encode=lambda kfrag: kfrag.to_bytes(),
|
||||
decode=KFrag.from_bytes)
|
||||
VerifiedKeyFrag,
|
||||
encode=bytes,
|
||||
decode=VerifiedKeyFrag.from_verified_bytes)
|
||||
_alice_verifying_key = RecordField(
|
||||
UmbralPublicKey,
|
||||
encode=bytes,
|
||||
|
|
|
@ -26,8 +26,7 @@ from cryptography import x509
|
|||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
from nucypher.blockchain.eth.networks import NetworksInventory
|
||||
from nucypher.crypto.signing import signature_splitter
|
||||
from nucypher.crypto.splitters import cfrag_splitter
|
||||
from nucypher.crypto.splitters import cfrag_splitter, signature_splitter
|
||||
from nucypher.utilities.logging import Logger
|
||||
|
||||
EXEMPT_FROM_VERIFICATION.bool_value(False)
|
||||
|
|
|
@ -44,7 +44,6 @@ from eth_utils import to_checksum_address
|
|||
from requests.exceptions import SSLError
|
||||
from twisted.internet import reactor, task
|
||||
from twisted.internet.defer import Deferred
|
||||
from umbral.signing import Signature
|
||||
|
||||
from nucypher.acumen.nicknames import Nickname
|
||||
from nucypher.acumen.perception import FleetSensor
|
||||
|
@ -58,7 +57,8 @@ from nucypher.config.storages import ForgetfulNodeStorage
|
|||
from nucypher.crypto.api import InvalidNodeCertificate, recover_address_eip_191, verify_eip_191
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.powers import DecryptingPower, NoSigningPower, SigningPower
|
||||
from nucypher.crypto.signing import signature_splitter
|
||||
from nucypher.crypto.splitters import signature_splitter
|
||||
from nucypher.crypto.umbral_adapter import Signature
|
||||
from nucypher.network import LEARNING_LOOP_VERSION
|
||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
|
|
|
@ -34,7 +34,7 @@ from mako import exceptions as mako_exceptions
|
|||
from mako.template import Template
|
||||
from maya import MayaDT
|
||||
from typing import Tuple
|
||||
from umbral.kfrags import KFrag
|
||||
from nucypher.crypto.umbral_adapter import KFrag
|
||||
from web3.exceptions import TimeExhausted
|
||||
|
||||
import nucypher
|
||||
|
@ -263,13 +263,15 @@ def _make_rest_app(datastore: Datastore, this_node, domain: str, log: Logger) ->
|
|||
kfrag_bytes = cleartext
|
||||
kfrag = KFrag.from_bytes(kfrag_bytes)
|
||||
|
||||
if not kfrag.verify(signing_pubkey=alices_verifying_key):
|
||||
try:
|
||||
verified_kfrag = kfrag.verify(signing_pubkey=alices_verifying_key)
|
||||
except VerificationError:
|
||||
return Response(f"Signature on {kfrag} is invalid", status=403)
|
||||
|
||||
with datastore.describe(PolicyArrangement, id_as_hex, writeable=True) as policy_arrangement:
|
||||
if not policy_arrangement.alice_verifying_key == alice.stamp.as_umbral_pubkey():
|
||||
return Response("Policy arrangement's signing key does not match sender's", status=403)
|
||||
policy_arrangement.kfrag = kfrag
|
||||
policy_arrangement.kfrag = verified_kfrag
|
||||
|
||||
# TODO: Sign the arrangement here. #495
|
||||
return "" # TODO: Return A 200, with whatever policy metadata.
|
||||
|
|
|
@ -30,9 +30,7 @@ from cryptography.hazmat.backends.openssl import backend
|
|||
from cryptography.hazmat.primitives import hashes
|
||||
from eth_utils import to_canonical_address, to_checksum_address
|
||||
from typing import Optional, Tuple
|
||||
from umbral.config import default_params
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.pre import Capsule
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey, Capsule
|
||||
|
||||
from nucypher.blockchain.eth.constants import ETH_ADDRESS_BYTE_LENGTH, ETH_HASH_BYTE_LENGTH
|
||||
from nucypher.characters.lawful import Bob, Character
|
||||
|
@ -40,9 +38,8 @@ from nucypher.crypto.api import encrypt_and_sign, keccak_digest
|
|||
from nucypher.crypto.api import verify_eip_191
|
||||
from nucypher.crypto.constants import HRAC_LENGTH
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.signing import InvalidSignature, Signature, signature_splitter, SignatureStamp
|
||||
from nucypher.crypto.splitters import capsule_splitter, key_splitter
|
||||
from nucypher.crypto.splitters import cfrag_splitter
|
||||
from nucypher.crypto.signing import InvalidSignature, Signature, SignatureStamp
|
||||
from nucypher.crypto.splitters import capsule_splitter, cfrag_splitter, key_splitter, signature_splitter
|
||||
from nucypher.crypto.utils import (
|
||||
canonical_address_from_umbral_key,
|
||||
)
|
||||
|
@ -101,7 +98,7 @@ class TreasureMap:
|
|||
@classmethod
|
||||
def splitter(cls):
|
||||
return BytestringKwargifier(cls,
|
||||
public_signature=Signature,
|
||||
public_signature=signature_splitter,
|
||||
hrac=(bytes, HRAC_LENGTH),
|
||||
message_kit=(UmbralMessageKit, VariableLengthBytestring)
|
||||
)
|
||||
|
@ -254,7 +251,7 @@ class SignedTreasureMap(TreasureMap):
|
|||
def splitter(cls):
|
||||
return BytestringKwargifier(cls,
|
||||
blockchain_signature=65,
|
||||
public_signature=Signature,
|
||||
public_signature=signature_splitter,
|
||||
hrac=(bytes, HRAC_LENGTH),
|
||||
message_kit=(UmbralMessageKit, VariableLengthBytestring)
|
||||
)
|
||||
|
@ -293,7 +290,6 @@ class WorkOrder:
|
|||
blockhash = bytes(blockhash)
|
||||
|
||||
expected_lengths = (
|
||||
(ursula_pubkey, 'ursula_pubkey', UmbralPublicKey.expected_bytes_length()),
|
||||
(alice_address, 'alice_address', ETH_ADDRESS_BYTE_LENGTH),
|
||||
(blockhash, 'blockhash', ETH_HASH_BYTE_LENGTH),
|
||||
# TODO: Why does ursula_identity_evidence has a default value of b''? for federated, perhaps?
|
||||
|
@ -313,7 +309,7 @@ class WorkOrder:
|
|||
def __bytes__(self):
|
||||
data = bytes(self.capsule) + bytes(self.signature)
|
||||
if self.cfrag and self.cfrag_signature:
|
||||
data += VariableLengthBytestring(self.cfrag) + bytes(self.cfrag_signature)
|
||||
data += bytes(self.cfrag) + bytes(self.cfrag_signature)
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
|
@ -394,7 +390,7 @@ class WorkOrder:
|
|||
@classmethod
|
||||
def from_rest_payload(cls, arrangement_id, rest_payload, ursula, alice_address):
|
||||
|
||||
payload_splitter = BytestringSplitter(Signature) + key_splitter + BytestringSplitter(ETH_HASH_BYTE_LENGTH)
|
||||
payload_splitter = signature_splitter + key_splitter + BytestringSplitter(ETH_HASH_BYTE_LENGTH)
|
||||
|
||||
signature, bob_verifying_key, blockhash, remainder = payload_splitter(rest_payload, return_remainder=True)
|
||||
tasks = {capsule: cls.PRETask(capsule, sig) for capsule, sig in cls.PRETask.input_splitter.repeat(remainder)}
|
||||
|
@ -444,12 +440,6 @@ class WorkOrder:
|
|||
ursula_verifying_key = self.ursula.stamp.as_umbral_pubkey()
|
||||
|
||||
for task, (cfrag, cfrag_signature) in zip(self.tasks.values(), cfrags_and_signatures):
|
||||
# Validate re-encryption metadata
|
||||
metadata_input = bytes(task.signature)
|
||||
metadata_as_signature = Signature.from_bytes(cfrag.proof.metadata)
|
||||
if not metadata_as_signature.verify(metadata_input, ursula_verifying_key):
|
||||
raise InvalidSignature(f"Invalid metadata for {cfrag}.")
|
||||
# TODO: Instead of raising, we should do something (#957)
|
||||
|
||||
# Validate re-encryption signatures
|
||||
if cfrag_signature.verify(bytes(cfrag), ursula_verifying_key):
|
||||
|
@ -525,7 +515,7 @@ class Revocation:
|
|||
REVOKE-<arrangement id to revoke><signature of the previous string>
|
||||
This is sent as a payload in a DELETE method to the /KFrag/ endpoint.
|
||||
"""
|
||||
revocation_splitter = BytestringSplitter((bytes, 7), (bytes, 32), Signature)
|
||||
revocation_splitter = BytestringSplitter((bytes, 7), (bytes, 32), signature_splitter)
|
||||
|
||||
def __init__(self, arrangement_id: bytes,
|
||||
signer: 'SignatureStamp' = None,
|
||||
|
|
|
@ -27,7 +27,7 @@ import os
|
|||
from bytestring_splitter import VariableLengthBytestring, BytestringKwargifier
|
||||
from constant_sorrow.constants import ALICE, BOB, NO_SIGNATURE
|
||||
from hexbytes.main import HexBytes
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
|
||||
from nucypher.characters.base import Character
|
||||
from nucypher.characters.lawful import Alice, Bob
|
||||
|
|
|
@ -34,16 +34,16 @@ from twisted._threads import AlreadyQuit
|
|||
from twisted.internet import reactor
|
||||
from twisted.internet.defer import ensureDeferred, Deferred
|
||||
from twisted.python.threadpool import ThreadPool
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.kfrags import KFrag
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey, KFrag
|
||||
|
||||
from nucypher.blockchain.eth.actors import BlockchainPolicyAuthor
|
||||
from nucypher.blockchain.eth.agents import PolicyManagerAgent, StakersReservoir, StakingEscrowAgent
|
||||
from nucypher.characters.lawful import Alice, Ursula
|
||||
from nucypher.crypto.api import keccak_digest, secure_random
|
||||
from nucypher.crypto.constants import HRAC_LENGTH, PUBLIC_KEY_LENGTH
|
||||
from nucypher.crypto.constants import HRAC_LENGTH
|
||||
from nucypher.crypto.kits import RevocationKit
|
||||
from nucypher.crypto.powers import DecryptingPower, SigningPower, TransactingPower
|
||||
from nucypher.crypto.splitters import key_splitter
|
||||
from nucypher.crypto.utils import construct_policy_id
|
||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
|
@ -57,7 +57,7 @@ class Arrangement:
|
|||
"""
|
||||
ID_LENGTH = 32
|
||||
|
||||
splitter = BytestringSplitter((UmbralPublicKey, PUBLIC_KEY_LENGTH), # alive_verifying_key
|
||||
splitter = BytestringSplitter(key_splitter, # alive_verifying_key
|
||||
(bytes, ID_LENGTH), # arrangement_id
|
||||
(bytes, VariableLengthBytestring)) # expiration
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import os
|
|||
import pytest
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey
|
||||
|
||||
from nucypher.cli.main import nucypher_cli
|
||||
from nucypher.policy.identity import Card
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey
|
||||
|
||||
from nucypher.cli.main import nucypher_cli
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import pytest
|
|||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey
|
||||
|
||||
from nucypher.blockchain.eth.actors import Worker
|
||||
from nucypher.cli.main import nucypher_cli
|
||||
|
|
|
@ -19,8 +19,7 @@ import os
|
|||
import pytest
|
||||
from eth_tester.exceptions import TransactionFailed
|
||||
from eth_utils import to_canonical_address, to_wei
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from umbral.signing import Signer
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, Signer
|
||||
from web3.contract import Contract
|
||||
|
||||
from nucypher.blockchain.economics import BaseEconomics
|
||||
|
|
|
@ -23,13 +23,13 @@ from cryptography.hazmat.backends.openssl import backend
|
|||
from cryptography.hazmat.primitives import hashes
|
||||
from eth_account.account import Account
|
||||
from eth_account.messages import HexBytes, SignableMessage, encode_defunct
|
||||
from eth_keys import KeyAPI as EthKeyAPI
|
||||
from eth_tester.exceptions import TransactionFailed
|
||||
from eth_utils import to_canonical_address, to_checksum_address, to_normalized_address
|
||||
from umbral.keys import UmbralPrivateKey, UmbralPublicKey
|
||||
from umbral.signing import Signer, Signature
|
||||
|
||||
from nucypher.crypto.api import keccak_digest, verify_eip_191
|
||||
from nucypher.crypto.utils import canonical_address_from_umbral_key
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, UmbralPublicKey, Signer, Signature
|
||||
|
||||
ALGORITHM_KECCAK256 = 0
|
||||
ALGORITHM_SHA256 = 1
|
||||
|
@ -51,7 +51,7 @@ def get_signature_recovery_value(message: bytes,
|
|||
"""
|
||||
|
||||
signature = bytes(signature)
|
||||
ecdsa_signature_size = Signature.expected_bytes_length()
|
||||
ecdsa_signature_size = 64 # two curve scalars
|
||||
if len(signature) != ecdsa_signature_size:
|
||||
raise ValueError(f"The signature size should be {ecdsa_signature_size} B.")
|
||||
|
||||
|
@ -66,6 +66,20 @@ def get_signature_recovery_value(message: bytes,
|
|||
"Either the message, the signature or the public key is not correct")
|
||||
|
||||
|
||||
def pubkey_as_address(umbral_pubkey):
|
||||
"""
|
||||
Returns the public key as b'0x' + keccak(uncompressed_bytes)[-20:]
|
||||
"""
|
||||
return to_normalized_address(canonical_address_from_umbral_key(umbral_pubkey).hex())
|
||||
|
||||
|
||||
def pubkey_as_uncompressed_bytes(umbral_pubkey):
|
||||
"""
|
||||
Returns the public key as uncompressed bytes (without the prefix, so 64 bytes long)
|
||||
"""
|
||||
return EthKeyAPI.PublicKey.from_compressed_bytes(bytes(umbral_pubkey)).to_bytes()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def signature_verifier(testerchain, deploy_contract):
|
||||
contract, _ = deploy_contract('SignatureVerifierMock')
|
||||
|
@ -83,9 +97,7 @@ def test_recover(testerchain, signature_verifier):
|
|||
# Generate Umbral key and extract "address" from the public key
|
||||
umbral_privkey = UmbralPrivateKey.gen_key()
|
||||
umbral_pubkey = umbral_privkey.get_pubkey()
|
||||
umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)
|
||||
signer_address = keccak_digest(umbral_pubkey_bytes[1:])
|
||||
signer_address = to_normalized_address(signer_address[12:])
|
||||
signer_address = pubkey_as_address(umbral_pubkey)
|
||||
|
||||
# Sign message
|
||||
signer = Signer(umbral_privkey)
|
||||
|
@ -121,9 +133,8 @@ def test_address(testerchain, signature_verifier):
|
|||
# Generate Umbral key and extract "address" from the public key
|
||||
umbral_privkey = UmbralPrivateKey.gen_key()
|
||||
umbral_pubkey = umbral_privkey.get_pubkey()
|
||||
umbral_pubkey_bytes = umbral_pubkey.to_bytes(is_compressed=False)[1:]
|
||||
signer_address = keccak_digest(umbral_pubkey_bytes)
|
||||
signer_address = to_normalized_address(signer_address[12:])
|
||||
signer_address = pubkey_as_address(umbral_pubkey)
|
||||
umbral_pubkey_bytes = pubkey_as_uncompressed_bytes(umbral_pubkey)
|
||||
|
||||
# Check extracting address in library
|
||||
result_address = signature_verifier.functions.toAddress(umbral_pubkey_bytes).call()
|
||||
|
@ -148,7 +159,7 @@ def test_verify(testerchain, signature_verifier):
|
|||
# Generate Umbral key
|
||||
umbral_privkey = UmbralPrivateKey.gen_key()
|
||||
umbral_pubkey = umbral_privkey.get_pubkey()
|
||||
umbral_pubkey_bytes = umbral_pubkey.to_bytes(is_compressed=False)
|
||||
umbral_pubkey_bytes = pubkey_as_uncompressed_bytes(umbral_pubkey)
|
||||
|
||||
# Sign message using SHA-256 hash
|
||||
signer = Signer(umbral_privkey)
|
||||
|
@ -161,15 +172,15 @@ def test_verify(testerchain, signature_verifier):
|
|||
# Verify signature
|
||||
assert signature_verifier.functions.verify(message,
|
||||
recoverable_signature,
|
||||
umbral_pubkey_bytes[1:],
|
||||
umbral_pubkey_bytes,
|
||||
ALGORITHM_SHA256).call()
|
||||
|
||||
# Verify signature using wrong key
|
||||
umbral_privkey = UmbralPrivateKey.gen_key()
|
||||
umbral_pubkey_bytes = umbral_privkey.get_pubkey().to_bytes(is_compressed=False)
|
||||
umbral_pubkey_bytes = pubkey_as_uncompressed_bytes(umbral_privkey.get_pubkey())
|
||||
assert not signature_verifier.functions.verify(message,
|
||||
recoverable_signature,
|
||||
umbral_pubkey_bytes[1:],
|
||||
umbral_pubkey_bytes,
|
||||
ALGORITHM_SHA256).call()
|
||||
|
||||
|
||||
|
@ -179,7 +190,7 @@ def test_verify_eip191(testerchain, signature_verifier):
|
|||
# Generate Umbral key
|
||||
umbral_privkey = UmbralPrivateKey.gen_key()
|
||||
umbral_pubkey = umbral_privkey.get_pubkey()
|
||||
umbral_pubkey_bytes = umbral_pubkey.to_bytes(is_compressed=False)
|
||||
umbral_pubkey_bytes = pubkey_as_uncompressed_bytes(umbral_pubkey)
|
||||
|
||||
#
|
||||
# Check EIP191 signatures: Version E
|
||||
|
@ -201,14 +212,14 @@ def test_verify_eip191(testerchain, signature_verifier):
|
|||
version_E = b'E'
|
||||
assert signature_verifier.functions.verifyEIP191(message,
|
||||
signature,
|
||||
umbral_pubkey_bytes[1:],
|
||||
umbral_pubkey_bytes,
|
||||
version_E).call()
|
||||
|
||||
# Of course, it'll fail if we try using version 0
|
||||
version_0 = b'\x00'
|
||||
assert not signature_verifier.functions.verifyEIP191(message,
|
||||
signature,
|
||||
umbral_pubkey_bytes[1:],
|
||||
umbral_pubkey_bytes,
|
||||
version_0).call()
|
||||
|
||||
# Check that the hash-based method also works independently
|
||||
|
@ -240,13 +251,13 @@ def test_verify_eip191(testerchain, signature_verifier):
|
|||
# On chain verify signature
|
||||
assert signature_verifier.functions.verifyEIP191(message,
|
||||
signature,
|
||||
umbral_pubkey_bytes[1:],
|
||||
umbral_pubkey_bytes,
|
||||
version_0).call()
|
||||
|
||||
# Of course, now it fails if we try with version E
|
||||
assert not signature_verifier.functions.verifyEIP191(message,
|
||||
signature,
|
||||
umbral_pubkey_bytes[1:],
|
||||
umbral_pubkey_bytes,
|
||||
version_E).call()
|
||||
|
||||
# Check that the hash-based method also works independently
|
||||
|
|
|
@ -19,8 +19,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
import os
|
||||
import pytest
|
||||
from eth_tester.exceptions import TransactionFailed
|
||||
from umbral import keys, pre
|
||||
from umbral.signing import Signer
|
||||
from nucypher.crypto.umbral_adapter import pre, Signer, UmbralPrivateKey
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
|
@ -31,11 +30,11 @@ def deserializer(testerchain, deploy_contract):
|
|||
|
||||
@pytest.fixture(scope="module")
|
||||
def fragments():
|
||||
delegating_privkey = keys.UmbralPrivateKey.gen_key()
|
||||
delegating_privkey = UmbralPrivateKey.gen_key()
|
||||
delegating_pubkey = delegating_privkey.get_pubkey()
|
||||
signing_privkey = keys.UmbralPrivateKey.gen_key()
|
||||
signing_privkey = UmbralPrivateKey.gen_key()
|
||||
signer = Signer(signing_privkey)
|
||||
priv_key_bob = keys.UmbralPrivateKey.gen_key()
|
||||
priv_key_bob = UmbralPrivateKey.gen_key()
|
||||
pub_key_bob = priv_key_bob.get_pubkey()
|
||||
kfrags = pre.generate_kfrags(delegating_privkey=delegating_privkey,
|
||||
signer=signer,
|
||||
|
@ -44,14 +43,12 @@ def fragments():
|
|||
N=4,
|
||||
sign_delegating_key=False,
|
||||
sign_receiving_key=False)
|
||||
# TODO: Use nucypher re-encryption metadata
|
||||
metadata = b"This is an example of metadata for re-encryption request"
|
||||
|
||||
_symmetric_key, capsule = pre._encapsulate(delegating_pubkey)
|
||||
capsule.set_correctness_keys(delegating=delegating_pubkey,
|
||||
receiving=pub_key_bob,
|
||||
verifying=signing_privkey.get_pubkey())
|
||||
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata)
|
||||
cfrag = pre.reencrypt(kfrags[0], capsule)
|
||||
return capsule, cfrag
|
||||
|
||||
|
||||
|
@ -71,40 +68,7 @@ def test_capsule(testerchain, deserializer, fragments):
|
|||
capsule, _cfrag = fragments
|
||||
capsule_bytes = capsule.to_bytes()
|
||||
result = deserializer.functions.toCapsule(capsule_bytes).call()
|
||||
assert bytes(capsule.point_e) == result[0] + result[1]
|
||||
assert bytes(capsule.point_v) == result[2] + result[3]
|
||||
assert capsule.bn_sig.to_bytes() == bytes(result[4])
|
||||
|
||||
|
||||
def test_proof(testerchain, deserializer, fragments):
|
||||
# Wrong number of bytes to deserialize proof
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
deserializer.functions.toCorrectnessProof(os.urandom(227)).call()
|
||||
|
||||
# Check random proof bytes without metadata
|
||||
proof_bytes = os.urandom(228)
|
||||
result = deserializer.functions.toCorrectnessProof(proof_bytes).call()
|
||||
assert proof_bytes == bytes().join(result)
|
||||
|
||||
# Check random proof bytes with metadata
|
||||
proof_bytes = os.urandom(270)
|
||||
result = deserializer.functions.toCorrectnessProof(proof_bytes).call()
|
||||
assert proof_bytes == bytes().join(result)
|
||||
|
||||
# Get real cfrag and proof
|
||||
_capsule, cfrag = fragments
|
||||
proof = cfrag.proof
|
||||
proof_bytes = proof.to_bytes()
|
||||
|
||||
# Check real proof
|
||||
result = deserializer.functions.toCorrectnessProof(proof_bytes).call()
|
||||
assert bytes(proof.point_e2) == result[0] + result[1]
|
||||
assert bytes(proof.point_v2) == result[2] + result[3]
|
||||
assert bytes(proof.point_kfrag_commitment) == result[4] + result[5]
|
||||
assert bytes(proof.point_kfrag_pok) == result[6] + result[7]
|
||||
assert proof.bn_sig.to_bytes() == result[8]
|
||||
assert bytes(proof.kfrag_signature) == result[9]
|
||||
assert bytes(proof.metadata) == result[10]
|
||||
assert b''.join(result) == capsule_bytes
|
||||
|
||||
|
||||
def test_cfrag(testerchain, deserializer, fragments):
|
||||
|
@ -123,20 +87,10 @@ def test_cfrag(testerchain, deserializer, fragments):
|
|||
|
||||
# Check real cfrag
|
||||
_capsule, cfrag = fragments
|
||||
proof = cfrag.proof
|
||||
cfrag_bytes = cfrag.to_bytes()
|
||||
result = deserializer.functions.toCapsuleFrag(cfrag_bytes).call()
|
||||
assert bytes(cfrag.point_e1) == result[0] + result[1]
|
||||
assert bytes(cfrag.point_v1) == result[2] + result[3]
|
||||
assert bytes(cfrag.kfrag_id) == result[4]
|
||||
assert bytes(cfrag.point_precursor) == result[5] + result[6]
|
||||
result = deserializer.functions.toCorrectnessProofFromCapsuleFrag(cfrag_bytes).call()
|
||||
assert bytes(proof.point_e2) == result[0] + result[1]
|
||||
assert bytes(proof.point_v2) == result[2] + result[3]
|
||||
assert bytes(proof.point_kfrag_commitment) == result[4] + result[5]
|
||||
assert bytes(proof.point_kfrag_pok) == result[6] + result[7]
|
||||
assert proof.bn_sig.to_bytes() == result[8]
|
||||
assert bytes(proof.kfrag_signature) == result[9]
|
||||
assert bytes(proof.metadata) == result[10]
|
||||
cfrag_bytes = bytes(cfrag)
|
||||
result_frag = deserializer.functions.toCapsuleFrag(cfrag_bytes).call()
|
||||
result_proof = deserializer.functions.toCorrectnessProofFromCapsuleFrag(cfrag_bytes).call()
|
||||
assert cfrag_bytes == b''.join(result_frag) + b''.join(result_proof)
|
||||
|
||||
|
||||
# TODO: Missing test for precomputed_data
|
||||
|
|
|
@ -18,9 +18,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
import pytest
|
||||
import pytest_twisted
|
||||
from twisted.internet import threads
|
||||
from umbral import pre
|
||||
from umbral.cfrags import CapsuleFrag
|
||||
from umbral.kfrags import KFrag
|
||||
from nucypher.crypto.umbral_adapter import pre, CapsuleFrag, KFrag
|
||||
|
||||
from nucypher.crypto.kits import PolicyMessageKit
|
||||
from nucypher.crypto.powers import DecryptingPower
|
||||
|
@ -200,13 +198,6 @@ def test_bob_can_issue_a_work_order_to_a_specific_ursula(enacted_federated_polic
|
|||
|
||||
with ursula.datastore.describe(PolicyArrangement, work_order.arrangement_id.hex()) as policy_arrangement:
|
||||
the_kfrag = policy_arrangement.kfrag
|
||||
the_correct_cfrag = pre.reencrypt(the_kfrag, capsule)
|
||||
|
||||
# The first CFRAG_LENGTH_WITHOUT_PROOF bytes (ie, the cfrag proper, not the proof material), are the same:
|
||||
assert bytes(the_cfrag)[:CapsuleFrag.expected_bytes_length()] == bytes(
|
||||
the_correct_cfrag)[:CapsuleFrag.expected_bytes_length()] # It's the correct cfrag!
|
||||
|
||||
assert the_correct_cfrag.verify_correctness(capsule)
|
||||
|
||||
# Now we'll show that Ursula saved the correct WorkOrder.
|
||||
with ursula.datastore.query_by(Workorder, filter_field='bob_verifying_key',
|
||||
|
@ -336,7 +327,6 @@ def test_bob_gathers_and_combines(enacted_federated_policy, federated_bob, feder
|
|||
|
||||
_success, cfrags = federated_bob._reencrypt(new_work_order)
|
||||
cfrag = cfrags[0]
|
||||
assert cfrag not in the_message_kit.capsule._attached_cfrags
|
||||
|
||||
the_message_kit.capsule.attach_cfrag(cfrags[0])
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
import datetime
|
||||
import maya
|
||||
import pytest
|
||||
from umbral.kfrags import KFrag
|
||||
from nucypher.crypto.umbral_adapter import KFrag
|
||||
|
||||
from nucypher.characters.lawful import Enrico
|
||||
from nucypher.crypto.api import keccak_digest
|
||||
|
|
|
@ -145,7 +145,8 @@ def test_key_validation(federated_bob):
|
|||
with pytest.raises(SpecificationError) as e:
|
||||
# lets just take a couple bytes off
|
||||
BobKeyInputRequirer().load({'bobkey': "02f0cb3f3a33f16255d9b2586e6c56570aa07bbeb1157e169f1fb114ffb40037"})
|
||||
assert "Unknown OpenSSL error." in str(e)
|
||||
assert "Could not convert input for bobkey to an Umbral Key" in str(e)
|
||||
assert "Expected 33 bytes, got 32" in str(e)
|
||||
|
||||
result = BobKeyInputRequirer().load(dict(bobkey=bytes(federated_bob.public_keys(DecryptingPower)).hex()))
|
||||
assert isinstance(result['bobkey'], bytes)
|
||||
|
|
|
@ -21,7 +21,7 @@ from unittest.mock import Mock
|
|||
import pytest
|
||||
import tempfile
|
||||
from constant_sorrow.constants import CERTIFICATE_NOT_SAVED, NO_KEYRING_ATTACHED
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey
|
||||
|
||||
from tests.constants import MOCK_IP_ADDRESS
|
||||
from nucypher.blockchain.eth.actors import StakeHolder
|
||||
|
|
|
@ -21,10 +21,9 @@ from unittest.mock import ANY
|
|||
|
||||
import pytest
|
||||
from constant_sorrow.constants import FEDERATED_ADDRESS
|
||||
from cryptography.hazmat.primitives.serialization.base import Encoding
|
||||
from cryptography.hazmat.primitives.serialization import Encoding
|
||||
from flask import Flask
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from umbral.signing import Signer
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, Signer
|
||||
|
||||
from nucypher.characters.lawful import Alice, Bob, Ursula
|
||||
from nucypher.config.constants import TEMPORARY_DOMAIN
|
||||
|
|
|
@ -19,7 +19,7 @@ import pytest
|
|||
import time
|
||||
from datetime import datetime
|
||||
from flask import Response
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey
|
||||
from unittest.mock import patch
|
||||
|
||||
from nucypher.characters.lawful import Ursula
|
||||
|
|
|
@ -33,8 +33,8 @@ from web3.contract import Contract
|
|||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from umbral.signing import Signer
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, Signer
|
||||
|
||||
from unittest.mock import Mock
|
||||
from zope.interface import provider
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ import shutil
|
|||
import time
|
||||
from eth_typing.evm import ChecksumAddress
|
||||
from typing import Set, Optional, List, Tuple
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey
|
||||
from web3.main import Web3
|
||||
from web3.types import Wei
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ from unittest.mock import patch
|
|||
|
||||
from nucypher.network.server import make_rest_app
|
||||
from tests.mock.serials import good_serials
|
||||
from umbral.config import default_params
|
||||
from umbral.keys import UmbralPublicKey
|
||||
from umbral.signing import Signature
|
||||
from nucypher.crypto.umbral_adapter import UmbralPublicKey, Signature
|
||||
|
||||
mock_cert_storage = patch("nucypher.config.storages.ForgetfulNodeStorage.store_node_certificate",
|
||||
new=lambda *args, **kwargs: "this_might_normally_be_a_filepath")
|
||||
|
@ -95,18 +93,11 @@ class NotAPublicKey:
|
|||
self.i_want_to_be_a_real_boy()
|
||||
return self.to_cryptography_pubkey()
|
||||
|
||||
@property
|
||||
def params(self):
|
||||
# Holy heck, metamock hacking.
|
||||
self.i_want_to_be_a_real_boy()
|
||||
return self.params
|
||||
|
||||
def __eq__(self, other):
|
||||
return bytes(self) == bytes(other)
|
||||
|
||||
|
||||
class NotAPrivateKey:
|
||||
params = default_params()
|
||||
|
||||
fake_signature = Signature.from_bytes(
|
||||
b'@\xbfS&\x97\xb3\x9e\x9e\xd3\\j\x9f\x0e\x8fY\x0c\xbeS\x08d\x0b%s\xf6\x17\xe2\xb6\xcd\x95u\xaapON\xd9E\xb3\x10M\xe1\xf4u\x0bL\x99q\xd6\r\x8e_\xe5I\x1e\xe5\xa2\xcf\xe5\x8be_\x077Gz'
|
||||
|
|
|
@ -63,7 +63,7 @@ def test_actor_with_signing_power_can_sign():
|
|||
|
||||
# ...or to get the signer's public key for verification purposes.
|
||||
# (note: we use the private _der_encoded_bytes here to test directly against the API, instead of Character)
|
||||
verification = api.verify_ecdsa(message, signature._der_encoded_bytes(),
|
||||
verification = api.verify_ecdsa(message, bytes(signature),
|
||||
stamp_of_the_signer.as_umbral_pubkey())
|
||||
|
||||
assert verification is True
|
||||
|
|
|
@ -19,7 +19,7 @@ from pathlib import Path
|
|||
|
||||
import pytest
|
||||
from constant_sorrow.constants import FEDERATED_ADDRESS
|
||||
from cryptography.hazmat.primitives.serialization.base import Encoding
|
||||
from cryptography.hazmat.primitives.serialization import Encoding
|
||||
|
||||
from nucypher.config.keyring import (
|
||||
_assemble_key_data,
|
||||
|
|
|
@ -18,7 +18,7 @@ import base64
|
|||
|
||||
import sha3
|
||||
from constant_sorrow.constants import PUBLIC_ONLY
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey
|
||||
|
||||
from nucypher.crypto import keypairs
|
||||
|
||||
|
@ -40,7 +40,7 @@ def test_keypair_with_umbral_keys():
|
|||
umbral_pubkey = umbral_privkey.get_pubkey()
|
||||
|
||||
new_keypair_from_priv = keypairs.Keypair(umbral_privkey)
|
||||
assert new_keypair_from_priv._privkey.bn_key.to_bytes() == umbral_privkey.bn_key.to_bytes()
|
||||
assert new_keypair_from_priv._privkey == umbral_privkey
|
||||
assert new_keypair_from_priv.pubkey.to_bytes() == umbral_pubkey.to_bytes()
|
||||
|
||||
new_keypair_from_pub = keypairs.Keypair(public_key=umbral_pubkey)
|
||||
|
@ -55,9 +55,6 @@ def test_keypair_serialization():
|
|||
pubkey_bytes = new_keypair.serialize_pubkey()
|
||||
assert pubkey_bytes == bytes(umbral_pubkey)
|
||||
|
||||
pubkey_b64 = new_keypair.serialize_pubkey(as_b64=True)
|
||||
assert pubkey_b64 == base64.urlsafe_b64encode(umbral_pubkey.to_bytes())
|
||||
|
||||
|
||||
def test_keypair_fingerprint():
|
||||
umbral_pubkey = UmbralPrivateKey.gen_key().get_pubkey()
|
||||
|
|
|
@ -21,38 +21,7 @@ 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
|
||||
|
||||
|
||||
def test_split_two_signatures():
|
||||
"""
|
||||
We make two random Signatures and concat them. Then split them and show that we got the proper result.
|
||||
"""
|
||||
sig1 = Signature.from_bytes(secure_random(64))
|
||||
sig2 = Signature.from_bytes(secure_random(64))
|
||||
sigs_concatted = sig1 + sig2
|
||||
two_signature_splitter = BytestringSplitter(Signature, Signature)
|
||||
rebuilt_sig1, rebuilt_sig2 = two_signature_splitter(sigs_concatted)
|
||||
assert (sig1, sig2) == (rebuilt_sig1, rebuilt_sig2)
|
||||
|
||||
|
||||
def test_split_signature_from_arbitrary_bytes():
|
||||
how_many_bytes = 10
|
||||
signature = Signature.from_bytes(secure_random(64))
|
||||
some_bytes = secure_random(how_many_bytes)
|
||||
splitter = BytestringSplitter(Signature, (bytes, how_many_bytes))
|
||||
|
||||
rebuilt_signature, rebuilt_bytes = splitter(signature + some_bytes)
|
||||
|
||||
|
||||
def test_trying_to_extract_too_many_bytes_raises_typeerror():
|
||||
how_many_bytes = 10
|
||||
too_many_bytes = 11
|
||||
signature = Signature.from_bytes(secure_random(64))
|
||||
some_bytes = secure_random(how_many_bytes)
|
||||
splitter = BytestringSplitter(Signature, (bytes, too_many_bytes))
|
||||
|
||||
with pytest.raises(BytestringSplittingError):
|
||||
rebuilt_signature, rebuilt_bytes = splitter(signature + some_bytes, return_remainder=True)
|
||||
from nucypher.crypto.splitters import signature_splitter
|
||||
|
||||
|
||||
def test_message_kit_serialization_via_enrico(enacted_federated_policy, federated_alice):
|
||||
|
|
|
@ -19,8 +19,7 @@ import os
|
|||
import pytest
|
||||
from bytestring_splitter import VariableLengthBytestring
|
||||
from eth_utils import to_canonical_address
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from umbral.signing import Signer
|
||||
from nucypher.crypto.umbral_adapter import UmbralPrivateKey, Signer
|
||||
|
||||
from nucypher.blockchain.eth.constants import ETH_HASH_BYTE_LENGTH, LENGTH_ECDSA_SIGNATURE_WITH_RECOVERY
|
||||
from nucypher.crypto.signing import SignatureStamp, InvalidSignature
|
||||
|
@ -62,7 +61,7 @@ def test_pre_task(mock_ursula_reencrypts, ursula, get_random_checksum_address):
|
|||
assert signature == deserialized_task.signature
|
||||
|
||||
# Attaching cfrags to the task
|
||||
cfrag_bytes = bytes(VariableLengthBytestring(cfrag.to_bytes()))
|
||||
cfrag_bytes = bytes(cfrag)
|
||||
cfrag_signature = ursula.stamp(cfrag_bytes)
|
||||
|
||||
task.attach_work_result(cfrag, cfrag_signature)
|
||||
|
@ -169,11 +168,6 @@ def test_work_order_with_multiple_capsules(mock_ursula_reencrypts,
|
|||
|
||||
# Testing WorkOrder.complete()
|
||||
|
||||
# Trying to complete this work order fails because the current task signatures are different from the ones created
|
||||
# when the re-encryption fixture ran. This is an expected effect of using that fixture, which makes the test simpler
|
||||
with pytest.raises(InvalidSignature, match="Invalid metadata"):
|
||||
work_order.complete(list(zip(cfrags, cfrag_signatures)))
|
||||
|
||||
# Let's use the original task signatures in our WorkOrder, instead
|
||||
for capsule, task_signature in zip(capsules, signatures):
|
||||
work_order.tasks[capsule].signature = task_signature
|
||||
|
|
|
@ -20,9 +20,7 @@ import contextlib
|
|||
import socket
|
||||
from cryptography.x509 import Certificate
|
||||
from typing import Iterable, List, Optional, Set
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from umbral.signing import Signer
|
||||
from nucypher.crypto.umbral_adapter import pre, UmbralPrivateKey, Signer
|
||||
|
||||
from nucypher.blockchain.eth.actors import Staker
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
|
@ -195,9 +193,7 @@ def _mock_ursula_reencrypts(ursula):
|
|||
bobs_signer = Signer(priv_key_bob)
|
||||
task_signature = bytes(bobs_signer(specification))
|
||||
|
||||
metadata = bytes(ursula.stamp(task_signature))
|
||||
|
||||
cfrag = pre.reencrypt(kfrags[0], capsule, metadata=metadata)
|
||||
cfrag = pre.reencrypt(kfrags[0], capsule)
|
||||
cfrag_signature = ursula.stamp(bytes(cfrag))
|
||||
|
||||
bob = Bob.from_public_keys(verifying_key=pub_key_bob)
|
||||
|
|
Loading…
Reference in New Issue