Post rebase cleanup for PR #2612; Umbral 0.2.x compatibility.

pull/2701/head
Kieran Prasch 2021-06-23 18:11:36 -07:00 committed by Kieran R. Prasch
parent 84d1e9b0c9
commit 8a54bd7e6d
19 changed files with 71 additions and 135 deletions

View File

@ -24,7 +24,6 @@ from nucypher.characters.control.specifications.exceptions import InvalidInputDa
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

View File

@ -55,7 +55,6 @@ 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
from umbral.signing import Signature
class BaseConfiguration(ABC):

View File

@ -33,12 +33,12 @@ from nucypher.crypto.tls import _read_tls_certificate, _TLS_CURVE, generate_self
from nucypher.crypto.umbral_adapter import (
SecretKey,
PublicKey,
Signer,
decrypt_original,
decrypt_reencrypted
decrypt_reencrypted,
Signature,
Signer
)
from nucypher.network.resources import get_static_resources
from umbral.signing import Signature, Signer
class Keypair(object):

View File

@ -20,6 +20,7 @@ import json
import os
import stat
import string
import time
from json import JSONDecodeError
from os.path import abspath
from pathlib import Path
@ -27,7 +28,6 @@ from secrets import token_bytes
from typing import Callable, ClassVar, Dict, List, Union, Optional, Tuple
import click
import time
from constant_sorrow.constants import KEYSTORE_LOCKED
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
@ -49,8 +49,8 @@ from nucypher.crypto.powers import (
DelegatingPower
)
from nucypher.crypto.tls import generate_self_signed_certificate
from nucypher.crypto.umbral_adapter import SecretKey, SecretKeyFactory
from nucypher.network.server import TLSHostingPower
from umbral.keys import UmbralPrivateKey
# HKDF
__HKDF_HASH_ALGORITHM = BLAKE2B
@ -81,6 +81,7 @@ class InvalidPassword(ValueError):
def __hkdf(key_material: bytes,
size: int,
info: Optional[bytes] = None,
salt: Optional[bytes] = None,
) -> bytes:
@ -92,7 +93,7 @@ def __hkdf(key_material: bytes,
kdf = HKDF(
algorithm=__HKDF_HASH_ALGORITHM,
length=__WRAPPING_KEY_LENGTH,
length=size,
salt=salt,
info=info,
backend=default_backend()
@ -114,12 +115,17 @@ def _derive_wrapping_key(password: str, salt: bytes) -> bytes:
return derived_key
def _derive_umbral_key(material: bytes, info: bytes) -> UmbralPrivateKey:
material = __hkdf(key_material=material, info=info)
__private = UmbralPrivateKey.from_bytes(key_bytes=material)
def _derive_umbral_key(material: bytes, info: bytes) -> SecretKey:
material = __hkdf(key_material=material, info=info, size=SecretKey.serialized_size())
__private = SecretKey.from_bytes(material)
return __private
def _derive_keying_material(material: bytes, info: bytes) -> bytes:
material = __hkdf(key_material=material, info=info, size=SecretKeyFactory.serialized_size())
return material
def _assemble_keystore(encrypted_secret: bytes, salt: bytes) -> Dict[str, Union[str, bytes]]:
encoded_key_data = {
'version': '2.0',
@ -252,7 +258,7 @@ def _parse_path(path: Path) -> Tuple[int, str]:
return created, keystore_id
def _derive_hosting_power(host: str, private_key: UmbralPrivateKey) -> TLSHostingPower:
def _derive_hosting_power(host: str, private_key: SecretKey) -> TLSHostingPower:
certificate, private_key = generate_self_signed_certificate(host=host, private_key=private_key)
keypair = HostingKeypair(host=host, private_key=private_key, certificate=certificate, generate_certificate=False)
power = TLSHostingPower(keypair=keypair, host=host)
@ -312,7 +318,7 @@ class Keystore:
# Derive verifying key (used as ID)
verifying_key = _derive_umbral_key(material=secret, info=_VERIFYING_INFO)
keystore_id = verifying_key.to_bytes().hex()[:Keystore._ID_SIZE]
keystore_id = bytes(verifying_key).hex()[:Keystore._ID_SIZE]
# Generate paths
keystore_dir = keystore_dir or Keystore._DEFAULT_DIR
@ -424,7 +430,8 @@ class Keystore:
power = power_class(keypair=keypair, *power_args, **power_kwargs)
elif issubclass(power_class, DerivedKeyBasedPower):
power = power_class(keying_material=__private_key.to_bytes(), *power_args, **power_kwargs)
__secret_material = _derive_keying_material(material=self.__secret, info=info)
power = power_class(keying_material=__secret_material, *power_args, **power_kwargs)
else:
failure_message = f"{power_class.__name__} is an invalid type for deriving a CryptoPower."

View File

@ -19,18 +19,20 @@
import datetime
import os
from ipaddress import IPv4Address
from typing import Tuple
from typing import Tuple, ClassVar
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.backends.openssl.ec import _EllipticCurvePrivateKey
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve, SECP256R1
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
from cryptography.hazmat.primitives.serialization import Encoding
from cryptography.x509 import Certificate
from cryptography.x509.oid import NameOID
from nucypher.crypto.umbral_adapter import SecretKey
_TLS_CERTIFICATE_ENCODING = Encoding.PEM
_TLS_CURVE = ec.SECP384R1
@ -60,17 +62,16 @@ def _read_tls_certificate(filepath: str) -> Certificate:
def generate_self_signed_certificate(host: str,
private_key: _EllipticCurvePrivateKey = None,
private_key: SecretKey = None,
days_valid: int = 365,
curve: EllipticCurve = _TLS_CURVE,
curve: ClassVar[EllipticCurve] = _TLS_CURVE,
) -> Tuple[Certificate, _EllipticCurvePrivateKey]:
if private_key:
private_key = private_key.to_cryptography_privkey()
private_bn = private_key.private_numbers().private_value
private_key = default_backend().derive_elliptic_curve_private_key(private_bn, curve)
private_bn = int.from_bytes(bytes(private_key), 'big')
private_key = ec.derive_private_key(private_value=private_bn, curve=curve())
else:
private_key = ec.generate_private_key(curve, default_backend())
private_key = ec.generate_private_key(curve(), default_backend())
public_key = private_key.public_key()
now = datetime.datetime.utcnow()

View File

@ -20,22 +20,19 @@ from typing import Union, Tuple
import sha3
from constant_sorrow import constants
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends.openssl.backend import backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from eth_account.account import Account
from eth_account.messages import encode_defunct
from eth_keys import KeyAPI as EthKeyAPI
from eth_utils.address import to_checksum_address
from nucypher.crypto.constants import SHA256
import nucypher.crypto.umbral_adapter as umbral
from nucypher.crypto.kits import UmbralMessageKit
from nucypher.crypto.signing import SignatureStamp
from nucypher.crypto.umbral_adapter import PublicKey
from umbral import pre
from umbral.keys import UmbralPublicKey, UmbralPrivateKey
from umbral.signing import Signature
from nucypher.crypto.umbral_adapter import Signature, PublicKey
SYSTEM_RAND = SystemRandom()
def construct_policy_id(label: bytes, stamp: bytes) -> bytes:
@ -54,8 +51,6 @@ def canonical_address_from_umbral_key(public_key: Union[PublicKey, SignatureStam
canonical_address = eth_pubkey.to_canonical_address()
return canonical_address
SYSTEM_RAND = SystemRandom()
def secure_random(num_bytes: int) -> bytes:
"""
@ -122,22 +117,6 @@ def sha256_digest(*messages: bytes) -> bytes:
return digest
def ecdsa_sign(message: bytes,
private_key: UmbralPrivateKey
) -> bytes:
"""
Accepts a hashed message and signs it with the private key given.
:param message: Message to hash and sign
:param private_key: Private key to sign with
:return: signature
"""
signing_key = private_key.to_cryptography_privkey()
signature_der_bytes = signing_key.sign(message, ec.ECDSA(SHA256))
return signature_der_bytes
def recover_address_eip_191(message: bytes, signature: bytes) -> str:
"""
Recover checksum address from EIP-191 signature
@ -157,34 +136,7 @@ def verify_eip_191(address: str, message: bytes, signature: bytes) -> bool:
return signature_is_valid
def verify_ecdsa(message: bytes,
signature: bytes,
public_key: UmbralPublicKey
) -> bool:
"""
Accepts a message and signature and verifies it with the
provided public key.
:param message: Message to verify
:param signature: Signature to verify
:param public_key: UmbralPublicKey to verify signature with
:return: True if valid, False if invalid.
"""
cryptography_pub_key = public_key.to_cryptography_pubkey()
try:
cryptography_pub_key.verify(
signature,
message,
ec.ECDSA(SHA256)
)
except InvalidSignature:
return False
return True
def encrypt_and_sign(recipient_pubkey_enc: UmbralPublicKey,
def encrypt_and_sign(recipient_pubkey_enc: PublicKey,
plaintext: bytes,
signer: 'SignatureStamp',
sign_plaintext: bool = True
@ -195,11 +147,11 @@ 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)
capsule, ciphertext = umbral.encrypt(recipient_pubkey_enc, sig_header + bytes(signature) + plaintext)
else:
# Encrypt first, sign second.
sig_header = constants.SIGNATURE_IS_ON_CIPHERTEXT
ciphertext, capsule = pre.encrypt(recipient_pubkey_enc, sig_header + plaintext)
capsule, ciphertext = umbral.encrypt(recipient_pubkey_enc, sig_header + plaintext)
signature = signer(ciphertext)
message_kit = UmbralMessageKit(ciphertext=ciphertext, capsule=capsule,
sender_verifying_key=signer.as_umbral_pubkey(),
@ -207,7 +159,7 @@ def encrypt_and_sign(recipient_pubkey_enc: UmbralPublicKey,
else:
# Don't sign.
signature = sig_header = constants.NOT_SIGNED
ciphertext, capsule = pre.encrypt(recipient_pubkey_enc, sig_header + plaintext)
capsule, ciphertext = umbral.encrypt(recipient_pubkey_enc, sig_header + plaintext)
message_kit = UmbralMessageKit(ciphertext=ciphertext, capsule=capsule)
return message_kit, signature

View File

@ -14,10 +14,11 @@ GNU Affero General Public License for more details.
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 nucypher.crypto.signing import Signature
from nucypher.crypto.umbral_adapter import PublicKey, VerifiedKeyFrag
from nucypher.crypto.umbral_adapter import PublicKey, VerifiedKeyFrag, Signature
from nucypher.datastore.base import DatastoreRecord, RecordField

View File

@ -27,7 +27,8 @@ import time
from bytestring_splitter import (
BytestringSplitter,
PartiallyKwargifiedBytes,
VariableLengthBytestring
VariableLengthBytestring,
BytestringSplittingError
)
from constant_sorrow import constant_or_bytes
from constant_sorrow.constants import (
@ -56,7 +57,6 @@ from nucypher.config.constants import SeednodeMetadata
from nucypher.config.storages import ForgetfulNodeStorage
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.utils import recover_address_eip_191, verify_eip_191
from nucypher.network import LEARNING_LOOP_VERSION
@ -64,7 +64,7 @@ from nucypher.network.exceptions import NodeSeemsToBeDown
from nucypher.network.middleware import RestMiddleware
from nucypher.network.protocols import SuspiciousActivity
from nucypher.utilities.logging import Logger
from umbral.signing import Signature
from nucypher.crypto.umbral_adapter import Signature
TEACHER_NODES = {
NetworksInventory.MAINNET: (
@ -76,6 +76,7 @@ TEACHER_NODES = {
NetworksInventory.IBEX: ('https://ibex.nucypher.network:9151',),
}
class NodeSprout(PartiallyKwargifiedBytes):
"""
An abridged node class designed for optimization of instantiation of > 100 nodes simultaneously.

View File

@ -33,9 +33,9 @@ from nucypher.blockchain.eth.constants import ETH_ADDRESS_BYTE_LENGTH, ETH_HASH_
from nucypher.characters.lawful import Bob, Character
from nucypher.crypto.constants import HRAC_LENGTH
from nucypher.crypto.kits import UmbralMessageKit
from nucypher.crypto.signing import InvalidSignature, Signature, SignatureStamp
from nucypher.crypto.signing import InvalidSignature, SignatureStamp
from nucypher.crypto.splitters import capsule_splitter, cfrag_splitter, key_splitter, signature_splitter
from nucypher.crypto.umbral_adapter import PublicKey, Capsule
from nucypher.crypto.umbral_adapter import PublicKey, Capsule, Signature
from nucypher.crypto.utils import (
canonical_address_from_umbral_key,
keccak_digest,
@ -270,6 +270,7 @@ class SignedTreasureMap(TreasureMap):
"Can't cast a DecentralizedTreasureMap to bytes until it has a blockchain signature (otherwise, is it really a 'DecentralizedTreasureMap'?")
return self._blockchain_signature + super().__bytes__()
class WorkOrder:
class PRETask:

View File

@ -16,43 +16,24 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import datetime
from collections import OrderedDict
from queue import Queue, Empty
from typing import Callable, Tuple, Sequence, Set, Optional, Iterable, List, Dict, Type
import math
import maya
import random
import time
from abc import ABC, abstractmethod
from typing import Tuple, Sequence, Optional, Iterable, List, Dict, Type
import maya
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
from constant_sorrow.constants import NOT_SIGNED
from eth_typing.evm import ChecksumAddress
from hexbytes import HexBytes
from twisted._threads import AlreadyQuit
from twisted.internet import reactor
from twisted.internet.defer import ensureDeferred, Deferred
from twisted.python.threadpool import ThreadPool
from nucypher.blockchain.eth.actors import BlockchainPolicyAuthor
from nucypher.blockchain.eth.agents import PolicyManagerAgent, StakersReservoir, StakingEscrowAgent
from nucypher.blockchain.eth.agents import StakersReservoir, StakingEscrowAgent
from nucypher.characters.lawful import Alice, Ursula
<<<<<<< HEAD
from nucypher.crypto.api import keccak_digest, secure_random
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.umbral_adapter import PublicKey, KeyFrag
from nucypher.crypto.utils import construct_policy_id
=======
from nucypher.crypto.constants import HRAC_LENGTH, PUBLIC_KEY_LENGTH
from nucypher.crypto.kits import RevocationKit
from nucypher.crypto.powers import DecryptingPower, SigningPower, TransactingPower
from nucypher.crypto.utils import construct_policy_id, secure_random, keccak_digest
>>>>>>> c20ee57ec... bulk renaming of Keyring -> Keystore
from nucypher.network.exceptions import NodeSeemsToBeDown
from nucypher.network.middleware import RestMiddleware
from nucypher.utilities.concurrency import WorkerPool, AllAtOnceFactory
from nucypher.utilities.logging import Logger
@ -520,7 +501,6 @@ class Policy(ABC):
class FederatedPolicy(Policy):
from nucypher.policy.collections import TreasureMap as _treasure_map_class # TODO: Circular Import
def _not_enough_ursulas_exception(self):
@ -543,7 +523,7 @@ class BlockchainPolicy(Policy):
A collection of n Arrangements representing a single Policy
"""
from nucypher.policy.collections import SignedTreasureMap as _treasure_map_class # TODO: Circular Import
from nucypher.policy.collections import SignedTreasureMap as _treasure_map_class
class InvalidPolicyValue(ValueError):
pass

View File

@ -36,9 +36,10 @@ from tests.constants import (
@mock.patch('nucypher.config.characters.AliceConfiguration.default_filepath', return_value='/non/existent/file')
def test_missing_configuration_file(default_filepath_mock, click_runner):
def test_missing_configuration_file(default_filepath_mock, click_runner, test_registry_source_manager):
cmd_args = ('alice', 'run', '--network', TEMPORARY_DOMAIN)
result = click_runner.invoke(nucypher_cli, cmd_args, catch_exceptions=False)
env = {NUCYPHER_ENVVAR_KEYSTORE_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD}
result = click_runner.invoke(nucypher_cli, cmd_args, catch_exceptions=False, env=env)
assert result.exit_code != 0
assert default_filepath_mock.called
assert "nucypher alice init" in result.output

View File

@ -27,7 +27,6 @@ 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 nucypher.crypto.api import keccak_digest, verify_eip_191
from nucypher.crypto.umbral_adapter import SecretKey, PublicKey, Signer, Signature
from nucypher.crypto.utils import (

View File

@ -14,14 +14,17 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import contextlib
import maya
import pytest
import time
from datetime import datetime
from flask import Response
from unittest.mock import patch
import maya
import pytest
from flask import Response
from nucypher.characters.lawful import Ursula
from nucypher.crypto.umbral_adapter import PublicKey, encrypt
from nucypher.datastore.base import RecordField

View File

@ -15,7 +15,6 @@
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import tempfile
from contextlib import contextmanager
from unittest.mock import patch

View File

@ -14,7 +14,6 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import base64
import sha3
from constant_sorrow.constants import PUBLIC_ONLY

View File

@ -23,7 +23,7 @@ from pathlib import Path
import pytest
from constant_sorrow.constants import KEYSTORE_LOCKED
from cryptography.hazmat.primitives.serialization.base import Encoding
from cryptography.hazmat.primitives._serialization import Encoding
from mnemonic.mnemonic import Mnemonic
from nucypher.crypto.keystore import (
@ -31,8 +31,8 @@ from nucypher.crypto.keystore import (
InvalidPassword,
validate_keystore_filename,
_MNEMONIC_LANGUAGE,
_derive_umbral_key,
_DELEGATING_INFO
_DELEGATING_INFO,
_derive_keying_material
)
from nucypher.crypto.keystore import (
_assemble_keystore,
@ -42,10 +42,10 @@ from nucypher.crypto.keystore import (
_read_keystore
)
from nucypher.crypto.powers import DecryptingPower, SigningPower, DelegatingPower
from nucypher.crypto.umbral_adapter import SecretKeyFactory
from nucypher.network.server import TLSHostingPower
from nucypher.utilities.networking import LOOPBACK_ADDRESS
from tests.constants import INSECURE_DEVELOPMENT_PASSWORD
from umbral.keys import UmbralKeyingMaterial
def test_invalid_keystore_path_parts(tmp_path, tmp_path_factory):
@ -241,7 +241,7 @@ def test_derive_signing_power(tmpdir):
keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
signing_power = keystore.derive_crypto_power(power_class=SigningPower)
assert signing_power.public_key().hex()
assert bytes(signing_power.public_key()).hex()
assert signing_power.keypair.fingerprint()
@ -249,7 +249,7 @@ def test_derive_decrypting_power(tmpdir):
keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
decrypting_power = keystore.derive_crypto_power(power_class=DecryptingPower)
assert decrypting_power.public_key().hex()
assert bytes(decrypting_power.public_key()).hex()
assert decrypting_power.keypair.fingerprint()
@ -257,9 +257,9 @@ def test_derive_delegating_power(tmpdir):
keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
delegating_power = keystore.derive_crypto_power(power_class=DelegatingPower)
private_key = _derive_umbral_key(info=_DELEGATING_INFO, material=keystore._Keystore__secret)
keying_material = UmbralKeyingMaterial.from_bytes(private_key.to_bytes()).to_bytes()
assert delegating_power._DelegatingPower__umbral_keying_material.to_bytes() == keying_material
private_key = _derive_keying_material(info=_DELEGATING_INFO, material=keystore._Keystore__secret)
keying_material = bytes(SecretKeyFactory.from_bytes(bytes(private_key)))
assert bytes(delegating_power._DelegatingPower__umbral_keying_material) == keying_material
assert delegating_power._get_privkey_from_label(label=b'some-label')

View File

@ -14,14 +14,9 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
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.utils import secure_random
from nucypher.crypto.kits import UmbralMessageKit
from nucypher.crypto.signing import Signature
from nucypher.crypto.splitters import signature_splitter
def test_message_kit_serialization_via_enrico(enacted_federated_policy, federated_alice):

View File

@ -17,7 +17,6 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import os
import pytest
from bytestring_splitter import VariableLengthBytestring
from eth_utils import to_canonical_address
from nucypher.blockchain.eth.constants import ETH_HASH_BYTE_LENGTH, LENGTH_ECDSA_SIGNATURE_WITH_RECOVERY

View File

@ -18,9 +18,10 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import contextlib
import socket
from cryptography.x509 import Certificate
from typing import Iterable, List, Optional, Set
from cryptography.x509 import Certificate
from nucypher.blockchain.eth.actors import Staker
from nucypher.blockchain.eth.interfaces import BlockchainInterface
from nucypher.characters.lawful import Bob
@ -31,7 +32,6 @@ from nucypher.crypto.utils import canonical_address_from_umbral_key
from nucypher.policy.collections import WorkOrder
from tests.constants import NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK
from tests.mock.datastore import MOCK_DB
from tests.utils.blockchain import TesterBlockchain
def select_test_port() -> int: