mirror of https://github.com/nucypher/nucypher.git
Enrico uses a web3 wallet to encrypt-then-sign.
parent
243448d015
commit
783f2dcd76
|
@ -81,6 +81,7 @@ from nucypher.blockchain.eth.registry import (
|
|||
BaseContractRegistry,
|
||||
InMemoryContractRegistry,
|
||||
)
|
||||
from nucypher.blockchain.eth.signers import Signer
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.characters.banners import (
|
||||
ALICE_BANNER,
|
||||
|
@ -1457,9 +1458,14 @@ class Enrico:
|
|||
|
||||
banner = ENRICO_BANNER
|
||||
|
||||
def __init__(self, encrypting_key: Union[PublicKey, DkgPublicKey]):
|
||||
def __init__(
|
||||
self,
|
||||
encrypting_key: Union[PublicKey, DkgPublicKey],
|
||||
signer: Optional[Signer] = None,
|
||||
):
|
||||
self.signer = signer
|
||||
self.signing_power = SigningPower()
|
||||
self._policy_pubkey = encrypting_key
|
||||
self._encrypting_key = encrypting_key
|
||||
self.log = Logger(f"{self.__class__.__name__}-{encrypting_key}")
|
||||
self.log.info(self.banner.format(encrypting_key))
|
||||
|
||||
|
@ -1477,20 +1483,27 @@ class Enrico:
|
|||
return message_kit
|
||||
|
||||
def encrypt_for_dkg(
|
||||
self, plaintext: bytes, conditions: Lingo
|
||||
self,
|
||||
plaintext: bytes,
|
||||
conditions: Lingo,
|
||||
) -> ThresholdMessageKit:
|
||||
if not self.signer:
|
||||
raise TypeError("This Enrico doesn't have a signer.")
|
||||
|
||||
validate_condition_lingo(conditions)
|
||||
conditions_json = json.dumps(conditions)
|
||||
access_conditions = Conditions(conditions_json)
|
||||
|
||||
# encrypt for DKG
|
||||
ciphertext, auth_data = encrypt_for_dkg(
|
||||
plaintext, self.policy_pubkey, access_conditions
|
||||
)
|
||||
|
||||
# authentication for AllowLogic
|
||||
# TODO Replace with `Signer` to be passed as parameter
|
||||
# authentication message for TACo
|
||||
header_hash = keccak_digest(bytes(ciphertext.header))
|
||||
authorization = self.signing_power.keypair.sign(header_hash).to_be_bytes()
|
||||
authorization = self.signer.sign_message(
|
||||
message=header_hash, account=self.signer.accounts[0]
|
||||
)
|
||||
|
||||
return ThresholdMessageKit(
|
||||
ciphertext=ciphertext,
|
||||
|
@ -1509,8 +1522,8 @@ class Enrico:
|
|||
|
||||
@property
|
||||
def policy_pubkey(self):
|
||||
if not self._policy_pubkey:
|
||||
if not self._encrypting_key:
|
||||
raise TypeError(
|
||||
"This Enrico doesn't know which policy encrypting key he used. Oh well."
|
||||
)
|
||||
return self._policy_pubkey
|
||||
return self._encrypting_key
|
||||
|
|
|
@ -2,6 +2,7 @@ import pytest
|
|||
import pytest_twisted
|
||||
from twisted.internet.threads import deferToThread
|
||||
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.blockchain.eth.trackers.dkg import EventScannerTask
|
||||
from nucypher.characters.lawful import Enrico
|
||||
from nucypher.policy.conditions.lingo import ConditionLingo
|
||||
|
@ -134,9 +135,12 @@ def test_ursula_ritualist(
|
|||
# prepare message and conditions
|
||||
plaintext = PLAINTEXT.encode()
|
||||
|
||||
# create Enrico
|
||||
signer = Web3Signer(client=testerchain.client)
|
||||
enrico = Enrico(encrypting_key=encrypting_key, signer=signer)
|
||||
|
||||
# encrypt
|
||||
# print(f'encrypting for DKG with key {bytes(encrypting_key.to_bytes()).hex()}')
|
||||
enrico = Enrico(encrypting_key=encrypting_key)
|
||||
print(f"encrypting for DKG with key {bytes(encrypting_key).hex()}")
|
||||
threshold_message_kit = enrico.encrypt_for_dkg(
|
||||
plaintext=plaintext, conditions=CONDITIONS
|
||||
)
|
||||
|
|
|
@ -60,6 +60,7 @@ def test_character_transacting_power_signing(testerchain, test_registry):
|
|||
restored_dict = restored_transaction.as_dict()
|
||||
assert to_checksum_address(restored_dict['to']) == transaction_dict['to']
|
||||
|
||||
|
||||
def test_transacting_power_sign_message(testerchain):
|
||||
|
||||
# Manually create a TransactingPower
|
||||
|
|
|
@ -10,6 +10,7 @@ from twisted.internet.threads import deferToThread
|
|||
from web3.datastructures import AttributeDict
|
||||
|
||||
from nucypher.blockchain.eth.agents import CoordinatorAgent
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.characters.lawful import Enrico, Ursula
|
||||
from nucypher.policy.conditions.lingo import ConditionLingo
|
||||
from tests.constants import TESTERCHAIN_CHAIN_ID
|
||||
|
@ -116,6 +117,7 @@ def execute_round_2(ritual_id: int, cohort: List[Ursula]):
|
|||
ursula.ritual_tracker._handle_ritual_event(event, get_block_when=lambda x: event)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_sign_message")
|
||||
@pytest.mark.parametrize('dkg_size, ritual_id, variant', PARAMS)
|
||||
@pytest_twisted.inlineCallbacks()
|
||||
def test_ursula_ritualist(
|
||||
|
@ -195,9 +197,12 @@ def test_ursula_ritualist(
|
|||
# prepare message and conditions
|
||||
plaintext = PLAINTEXT.encode()
|
||||
|
||||
# create Enrico
|
||||
signer = Web3Signer(client=testerchain.client)
|
||||
enrico = Enrico(encrypting_key=encrypting_key, signer=signer)
|
||||
|
||||
# encrypt
|
||||
# print(f'encrypting for DKG with key {bytes(encrypting_key.to_bytes()).hex()}')
|
||||
enrico = Enrico(encrypting_key=encrypting_key)
|
||||
print(f"encrypting for DKG with key {bytes(encrypting_key).hex()}")
|
||||
threshold_message_kit = enrico.encrypt_for_dkg(
|
||||
plaintext=plaintext, conditions=CONDITIONS
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import pytest
|
||||
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.characters.chaotic import (
|
||||
NiceGuyEddie,
|
||||
ThisBobAlwaysDecrypts,
|
||||
|
@ -14,10 +15,11 @@ from tests.constants import (
|
|||
)
|
||||
|
||||
|
||||
def _attempt_decryption(BobClass, plaintext):
|
||||
def _attempt_decryption(BobClass, plaintext, testerchain):
|
||||
trinket = 80 # Doens't matter.
|
||||
|
||||
enrico = NiceGuyEddie(encrypting_key=trinket)
|
||||
signer = Web3Signer(client=testerchain.client)
|
||||
enrico = NiceGuyEddie(encrypting_key=trinket, signer=signer)
|
||||
bob = BobClass(
|
||||
registry=MOCK_REGISTRY_FILEPATH,
|
||||
domain="lynx",
|
||||
|
@ -46,13 +48,15 @@ def _attempt_decryption(BobClass, plaintext):
|
|||
return decrypted_cleartext
|
||||
|
||||
|
||||
def test_user_controls_success():
|
||||
@pytest.mark.usefixtures("mock_sign_message")
|
||||
def test_user_controls_success(testerchain):
|
||||
plaintext = b"ever thus to deadbeats"
|
||||
result = _attempt_decryption(ThisBobAlwaysDecrypts, plaintext)
|
||||
result = _attempt_decryption(ThisBobAlwaysDecrypts, plaintext, testerchain)
|
||||
assert bytes(result) == bytes(plaintext)
|
||||
|
||||
|
||||
def test_user_controls_failure():
|
||||
@pytest.mark.usefixtures("mock_sign_message")
|
||||
def test_user_controls_failure(testerchain):
|
||||
plaintext = b"ever thus to deadbeats"
|
||||
with pytest.raises(Ursula.NotEnoughUrsulas):
|
||||
_ = _attempt_decryption(ThisBobAlwaysFails, plaintext)
|
||||
_ = _attempt_decryption(ThisBobAlwaysFails, plaintext, testerchain)
|
||||
|
|
|
@ -151,6 +151,7 @@ def test_tls_hosting_certificate_remains_the_same(temp_dir_path, mocker):
|
|||
recreated_ursula.disenchant()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_sign_message")
|
||||
def test_ritualist(temp_dir_path, testerchain, dkg_public_key):
|
||||
keystore = Keystore.generate(
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=temp_dir_path
|
||||
|
@ -186,11 +187,15 @@ def test_ritualist(temp_dir_path, testerchain, dkg_public_key):
|
|||
},
|
||||
}
|
||||
|
||||
# create enrico
|
||||
signer = Web3Signer(client=testerchain.client)
|
||||
enrico = Enrico(encrypting_key=dkg_public_key, signer=signer)
|
||||
|
||||
# encrypt
|
||||
enrico = Enrico(encrypting_key=dkg_public_key)
|
||||
threshold_message_kit = enrico.encrypt_for_dkg(
|
||||
plaintext=plaintext, conditions=CONDITIONS
|
||||
)
|
||||
|
||||
decryption_request = ThresholdDecryptionRequest(
|
||||
ritual_id=ritual_id,
|
||||
variant=FerveoVariant.Simple,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import os
|
||||
from pathlib import Path
|
||||
from typing import Iterable, Optional
|
||||
|
||||
|
@ -20,6 +21,7 @@ from nucypher.blockchain.eth.interfaces import (
|
|||
from nucypher.blockchain.eth.networks import NetworksInventory
|
||||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
|
||||
from nucypher.blockchain.eth.signers import KeystoreSigner
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
from nucypher.characters.lawful import Ursula
|
||||
from nucypher.cli.types import ChecksumAddress
|
||||
from nucypher.config.characters import UrsulaConfiguration
|
||||
|
@ -59,6 +61,14 @@ def mock_sample_reservoir(testerchain, mock_contract_agency):
|
|||
mock_agent.get_staking_provider_reservoir = mock_reservoir
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def mock_sign_message(mocker):
|
||||
mocked_sign_message = mocker.patch.object(
|
||||
Web3Signer, "sign_message", return_value=os.urandom(32)
|
||||
)
|
||||
return mocked_sign_message
|
||||
|
||||
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def mock_application_agent(
|
||||
testerchain, application_economics, mock_contract_agency, mocker
|
||||
|
|
|
@ -7,7 +7,7 @@ from typing import Union
|
|||
|
||||
from hexbytes import HexBytes
|
||||
|
||||
from nucypher.blockchain.eth.clients import EthereumClient
|
||||
from nucypher.blockchain.eth.clients import EthereumTesterClient
|
||||
from nucypher.blockchain.eth.networks import NetworksInventory
|
||||
from nucypher.blockchain.eth.registry import (
|
||||
BaseContractRegistry,
|
||||
|
@ -82,7 +82,7 @@ class MockBlockchain(TesterBlockchain):
|
|||
return self.FAKE_RECEIPT
|
||||
|
||||
|
||||
class MockEthereumClient(EthereumClient):
|
||||
class MockEthereumClient(EthereumTesterClient):
|
||||
|
||||
def __init__(self, w3):
|
||||
super().__init__(w3=w3, node_technology=None, version=None, platform=None, backend=None)
|
||||
|
|
Loading…
Reference in New Issue