nucypher.characters

Submodules

class Character(domain: str = None, known_node_class: object = None, is_me: bool = True, federated_only: bool = False, checksum_address: str = NO_BLOCKCHAIN_CONNECTION, network_middleware: nucypher.network.middleware.RestMiddleware = None, keyring: nucypher.config.keyring.NucypherKeyring = None, keyring_root: str = None, crypto_power: nucypher.crypto.powers.CryptoPower = None, crypto_power_ups: List[nucypher.crypto.powers.CryptoPowerUp] = None, provider_uri: str = None, signer: nucypher.blockchain.eth.signers.base.Signer = None, registry: nucypher.blockchain.eth.registry.BaseContractRegistry = None, *args, **kwargs)

Bases: nucypher.network.nodes.Learner

A base-class for any character in our cryptography protocol narrative.

exception SuspiciousActivity

Bases: RuntimeError

raised when an action appears to amount to malicious conduct.

property name
property stamp
property canonical_public_address
property checksum_address
classmethod from_config(config, **overrides)nucypher.characters.base.Character
classmethod from_public_keys(powers_and_material: Dict = None, verifying_key: Union[bytes, umbral.keys.UmbralPublicKey] = None, encrypting_key: Union[bytes, umbral.keys.UmbralPublicKey] = None, *args, **kwargs)nucypher.characters.base.Character

Sometimes we discover a Character and, at the same moment, learn the public parts of more of their powers. Here, we take a Dict (powers_and_material) in the format {CryptoPowerUp class: material}, where material can be bytes or UmbralPublicKey.

Each item in the collection will have the CryptoPowerUp instantiated with the given material, and the resulting CryptoPowerUp instance consumed by the Character.

Alternatively, you can pass directly a verifying public key (for SigningPower) and/or an encrypting public key (for DecryptionPower).

store_metadata(filepath: str)str

Save this node to the disk. :param filepath: Output filepath to save node metadata. :return: Output filepath

encrypt_for(recipient: nucypher.characters.base.Character, plaintext: bytes, sign: bool = True, sign_plaintext=True)tuple

Encrypts plaintext for recipient actor. Optionally signs the message as well.

Parameters
  • recipient – The character whose public key will be used to encrypt cleartext.

  • plaintext – The secret to be encrypted.

  • sign – Whether or not to sign the message.

  • sign_plaintext – When signing, the cleartext is signed if this is True, Otherwise, the resulting ciphertext is signed.

Returns

A tuple, (ciphertext, signature). If sign==False, then signature will be NOT_SIGNED.

verify_from(stranger: nucypher.characters.base.Character, message_kit: Union[nucypher.crypto.kits.PolicyMessageKit, bytes], signature: umbral.signing.Signature = None, decrypt=False, label=None)bytes

Inverse of encrypt_for.

Parameters
  • stranger – A Character instance representing the actor whom the sender claims to be. We check the public key owned by this Character instance to verify.

  • message_kit – the message to be (perhaps decrypted and) verified.

  • signature – The signature to check.

  • decrypt – Whether or not to decrypt the messages.

  • label – A label used for decrypting messages encrypted under its associated policy encrypting key

Returns

Whether or not the signature is valid, the decrypted plaintext or NO_DECRYPTION_PERFORMED

decrypt(message_kit: nucypher.crypto.kits.PolicyMessageKit, label: Optional[bytes] = None)bytes
sign(message)
public_keys(power_up_class: ClassVar)

Pass a power_up_class, get the public material for this Character which corresponds to that class - whatever type of object that may be.

If the Character doesn’t have the power corresponding to that class, raises the appropriate PowerUpError (ie, NoSigningPower or NoDecryptingPower).

make_rpc_controller(crash_on_error: bool = False)
make_cli_controller(crash_on_error: bool = False)
disenchant()
class Felix(db_filepath: str, rest_host: str, rest_port: int, client_password: str = None, crash_on_error: bool = False, distribute_ether: bool = True, registry: nucypher.blockchain.eth.registry.BaseContractRegistry = None, *args, **kwargs)

Bases: nucypher.characters.base.Character, nucypher.blockchain.eth.actors.NucypherTokenActor

A NuCypher ERC20 faucet / Airdrop scheduler.

Felix is a web application that gives NuCypher testnet tokens to registered addresses with a scheduled reduction of disbursement amounts, and an HTTP endpoint for handling new address registration.

The main goal of Felix is to provide a source of testnet tokens for research and the development of production-ready nucypher dApps.

DISTRIBUTION_INTERVAL = 60
DISBURSEMENT_INTERVAL = 8760
STAGING_DELAY = 10
BATCH_SIZE = 10
MULTIPLIER = Decimal('0.9')
MINIMUM_DISBURSEMENT = 1000000000000000000
ETHER_AIRDROP_AMOUNT = 100000000000000000
MAX_INDIVIDUAL_REGISTRATIONS = 3
LEARNING_TIMEOUT = 30
exception NoDatabase

Bases: RuntimeError

start_learning_loop(now=False)

Felix needs to not even be a Learner, but since it is at the moment, it certainly needs not to learn.

make_web_app()
create_tables()None
start(host: str, port: int, web_services: bool = True, distribution: bool = True, crash_on_error: bool = False)
start_distribution(now: bool = True)bool

Start token distribution

stop_distribution()bool

Start token distribution

airdrop_tokens()

Calculate airdrop eligibility via faucet registration and transfer tokens to selected recipients.

class Alice(is_me: bool = True, federated_only: bool = False, signer=None, checksum_address: str = None, client_password: str = None, cache_password: bool = False, m: int = None, n: int = None, rate: int = None, duration_periods: int = None, timeout: int = 10, network_middleware: nucypher.network.middleware.RestMiddleware = None, controller: bool = True, *args, **kwargs)

Bases: nucypher.characters.base.Character, nucypher.blockchain.eth.actors.BlockchainPolicyAuthor

banner = '\n\n / \\ | (_) ___ ___\n / _ \\ | | |/ __/ _ \\\n / ___ \\| | | (_| __/\n /_/ \\_|_|_|\\___\\___|\n\n the Authority.\n'
add_active_policy(active_policy)

Adds a Policy object that is active on the NuCypher network to Alice’s active_policies dictionary by the policy ID. The policy ID is a Keccak hash of the policy label and Bob’s stamp bytes

generate_kfrags(bob: nucypher.characters.lawful.Bob, label: bytes, m: int = None, n: int = None) → List

Generates re-encryption key frags (“KFrags”) and returns them.

These KFrags can be used by Ursula to re-encrypt a Capsule for Bob so that he can activate the Capsule.

Parameters
  • bob – Bob instance which will be able to decrypt messages re-encrypted with these kfrags.

  • m – Minimum number of kfrags needed to activate a Capsule.

  • n – Total number of kfrags to generate

create_policy(bob: nucypher.characters.lawful.Bob, label: bytes, **policy_params)

Create a Policy so that Bob has access to all resources under label. Generates KFrags and attaches them.

generate_policy_parameters(m: int = None, n: int = None, duration_periods: int = None, expiration: maya.core.MayaDT = None, *args, **kwargs)dict

Construct policy creation from parameters or overrides.

grant(bob: nucypher.characters.lawful.Bob, label: bytes, handpicked_ursulas: set = None, discover_on_this_thread: bool = True, timeout: int = None, publish_treasure_map: bool = True, block_until_success_is_reasonably_likely: bool = True, **policy_params)
get_policy_encrypting_key_from_label(label: bytes) → umbral.keys.UmbralPublicKey
revoke(policy) → Dict

Parses the treasure map and revokes arrangements in it. If any arrangements can’t be revoked, then the node_id is added to a dict as a key, and the revocation and Ursula’s response is added as a value.

decrypt_message_kit(message_kit: nucypher.crypto.kits.PolicyMessageKit, data_source: nucypher.characters.base.Character, label: bytes) → List[bytes]

Decrypt this Alice’s own encrypted data.

I/O signatures match Bob’s retrieve interface.

make_web_controller(crash_on_error: bool = False)
class Bob(treasure_maps: Optional[Dict] = None, controller: bool = True, *args, **kwargs)

Bases: nucypher.characters.base.Character

banner = '\n\noooooooooo oooo \n 888 888 ooooooo 888ooooo \n 888oooo88 888 888 888 888\n 888 888 888 888 888 888\no888ooo888 88ooo88 o888ooo88 \n\nthe BUIDLer.\n'
exception IncorrectCFragsReceived(evidence: List)

Bases: Exception

Raised when Bob detects incorrect CFrags returned by some Ursulas

peek_at_treasure_map(treasure_map=None, map_id=None)

Take a quick gander at the TreasureMap matching map_id to see which nodes are already known to us.

Don’t do any learning, pinging, or anything other than just seeing whether we know or don’t know the nodes.

Return two sets: nodes that are unknown to us, nodes that are known to us.

follow_treasure_map(treasure_map=None, map_id=None, block=False, new_thread=False, timeout=10, allow_missing=0)

Follows a known TreasureMap, looking it up by map_id.

Determines which Ursulas are known and which are unknown.

If block, will block until either unknown nodes are discovered or until timeout seconds have elapsed. After timeout seconds, if more than allow_missing nodes are still unknown, raises NotEnoughUrsulas.

If block and new_thread, does the same thing but on a different thread, returning a Deferred which fires after the blocking has concluded.

Otherwise, returns (unknown_nodes, known_nodes).

# TODO: Check if nodes are up, declare them phantom if not. 567

get_treasure_map(alice_verifying_key, label)
make_compass_for_alice(alice)
construct_policy_hrac(verifying_key: Union[bytes, umbral.keys.UmbralPublicKey], label: bytes)bytes
construct_hrac_and_map_id(verifying_key, label)
get_treasure_map_from_known_ursulas(network_middleware, map_identifier, timeout=3)

Iterate through the nodes we know, asking for the TreasureMap. Return the first one who has it.

work_orders_for_capsules(*capsules, alice_verifying_key: umbral.keys.UmbralPublicKey = None, map_id: str = None, treasure_map: TreasureMap = None, num_ursulas: int = None)
get_reencrypted_cfrags(work_order, retain_cfrags=False)
join_policy(label, alice_verifying_key, node_list=None, block=False)
retrieve(*message_kits: nucypher.crypto.kits.PolicyMessageKit, alice_verifying_key: umbral.keys.UmbralPublicKey = None, label: bytes = None, enrico: Enrico = None, retain_cfrags: bool = False, use_attached_cfrags: bool = False, use_precedent_work_orders: bool = False, policy_encrypting_key: umbral.keys.UmbralPublicKey = None, treasure_map: Union[TreasureMap, bytes] = None)
matching_nodes_among(nodes: nucypher.acumen.perception.FleetSensor, no_less_than=7)
make_web_controller(crash_on_error: bool = False)
class Ursula(rest_host: str, rest_port: int, domain: str = None, certificate: cryptography.x509.base.Certificate = None, certificate_filepath: str = None, db_filepath: str = None, is_me: bool = True, interface_signature=None, timestamp=None, availability_check: bool = False, prune_datastore: bool = True, decentralized_identity_evidence: bytes = NOT_SIGNED, checksum_address: str = None, worker_address: str = None, block_until_ready: bool = True, work_tracker: nucypher.blockchain.eth.token.WorkTracker = None, start_working_now: bool = True, client_password: str = None, abort_on_learning_error: bool = False, federated_only: bool = False, start_learning_now: bool = None, crypto_power=None, tls_curve: cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve = None, known_nodes: Iterable = None, **character_kwargs)

Bases: nucypher.network.nodes.Teacher, nucypher.characters.base.Character, nucypher.blockchain.eth.actors.Worker

banner = '\n\n\n ,ggg, gg \ndP""Y8a 88 ,dPYb, \nYb, `88 88 IP\'`Yb \n `" 88 88 I8 8I \n 88 88 I8 8\' \n 88 88 ,gggggg, ,g, gg gg I8 dP ,gggg,gg \n 88 88 dP""""8I ,8\'8, I8 8I I8dP dP" "Y8I \n 88 88 ,8\' 8I ,8\' Yb I8, ,8I I8P i8\' ,8I \n Y8b,____,d88,,dP Y8,,8\'_ 8) ,d8b, ,d8b,,d8b,_ ,d8, ,d8b,\n "Y888888P"Y88P `Y8P\' "YY8P8P8P\'"Y88P"`Y88P\'"Y88P"Y8888P"`Y8\n\n\nthe Untrusted Re-Encryption Proxy.\n{}\n'
exception NotEnoughUrsulas

Bases: nucypher.network.nodes.Learner.NotEnoughTeachers, nucypher.blockchain.eth.agents.StakingEscrowAgent.NotEnoughStakers

All Characters depend on knowing about enough Ursulas to perform their role. This exception is raised when a piece of logic can’t proceed without more Ursulas.

exception NotFound

Bases: Exception

run(emitter: nucypher.characters.control.emitters.StdoutEmitter = None, hendrix: bool = True, learning: bool = True, availability: bool = True, worker: bool = True, pruning: bool = True, interactive: bool = False, start_reactor: bool = True, prometheus_config: PrometheusMetricsConfig = None)None

Schedule and start select ursula services, then optionally start the reactor.

stop(halt_reactor: bool = False)None

Stop services for partially or fully initialized characters. # CAUTION #

rest_information()
property rest_interface
get_deployer()
rest_server_certificate()
classmethod from_rest_url(network_middleware: nucypher.network.middleware.RestMiddleware, host: str, port: int, certificate_filepath, *args, **kwargs)
classmethod from_seednode_metadata(seednode_metadata, *args, **kwargs)

Essentially another deserialization method, but this one doesn’t reconstruct a complete node from bytes; instead it’s just enough to connect to and verify a node.

NOTE: This is a federated only method.

classmethod from_teacher_uri(federated_only: bool, teacher_uri: str, min_stake: int, network_middleware: nucypher.network.middleware.RestMiddleware = None, registry: nucypher.blockchain.eth.registry.BaseContractRegistry = None, retry_attempts: int = 2, retry_interval: int = 2)nucypher.characters.lawful.Ursula
classmethod from_seed_and_stake_info(seed_uri: str, federated_only: bool = False, minimum_stake: int = 0, registry: nucypher.blockchain.eth.registry.BaseContractRegistry = None, network_middleware: nucypher.network.middleware.RestMiddleware = None, *args, **kwargs)nucypher.characters.lawful.Ursula
classmethod payload_splitter(splittable, partial=False)
classmethod is_compatible_version(version: int)bool
classmethod from_bytes(ursula_as_bytes: bytes, version: int = INCLUDED_IN_BYTESTRING, fail_fast=False)nucypher.characters.lawful.Ursula
classmethod from_processed_bytes(**processed_objects)

A convenience method for completing the maturation of a NodeSprout. TODO: Either deprecate or consolidate this logic; it’s mostly just workarounds. NRN

classmethod batch_from_bytes(ursulas_as_bytes: Iterable[bytes], fail_fast: bool = False) → List[nucypher.characters.lawful.Ursula]
classmethod from_storage(node_storage: nucypher.config.storages.NodeStorage, checksum_adress: str, federated_only: bool = False)nucypher.characters.lawful.Ursula
property datastore
property rest_url
property rest_app
interface_info_with_metadata()
class Enrico(policy_encrypting_key=None, controller: bool = True, *args, **kwargs)

Bases: nucypher.characters.base.Character

A Character that represents a Data Source that encrypts data for some policy’s public key

banner = '\n ___ \n )_ _ _ o _ _ \n(__ ) ) ) ( (_ (_) \n\nthe Encryptor.\n{}\n'
encrypt_message(plaintext: bytes) → Tuple[nucypher.crypto.kits.PolicyMessageKit, umbral.signing.Signature]
classmethod from_alice(alice: nucypher.characters.lawful.Alice, label: bytes)
Parameters
  • alice – Not a stranger. This is your Alice who will derive the policy keypair, leaving Enrico with the public part.

  • label – The label with which to derive the key.

Returns

property policy_pubkey
make_web_controller(crash_on_error: bool = False)
class Vladimir(*args, **kwargs)

Bases: nucypher.characters.lawful.Ursula

The power of Ursula, but with a heart forged deep in the mountains of Microsoft or a State Actor or whatever.

fraud_address = '0xbad022A87Df21E4c787C7B1effD5077014b8CC45'
fraud_key = 'a75d701cc4199f7646909d15f22e2e0ef6094b3e2aa47a188f35f47e8932a7b9'
db_filepath = ':memory:'
classmethod from_target_ursula(target_ursula: nucypher.characters.lawful.Ursula, claim_signing_key: bool = False, attach_transacting_key: bool = True)nucypher.characters.unlawful.Vladimir

Sometimes Vladimir seeks to attack or imitate a specific target Ursula.

TODO: This is probably a more instructive method if it takes a bytes representation instead of the entire Ursula.

classmethod attach_transacting_key(blockchain)

Upload Vladimir’s ETH keys to the keychain via web3.

publish_fraudulent_treasure_map(legit_treasure_map, target_node)

If I see a TreasureMap being published, I can substitute my own payload and hope that Ursula will store it for me for free.

class Amonia(is_me: bool = True, federated_only: bool = False, signer=None, checksum_address: str = None, client_password: str = None, cache_password: bool = False, m: int = None, n: int = None, rate: int = None, duration_periods: int = None, timeout: int = 10, network_middleware: nucypher.network.middleware.RestMiddleware = None, controller: bool = True, *args, **kwargs)

Bases: nucypher.characters.lawful.Alice

Separated at birth, Alice’s sister is lighter than air and has a pungent smell.

classmethod from_lawful_alice(alice)
static enact_without_tabulating_responses(policy, network_middleware, *_args, **_kwargs)
grant_without_paying(*args, **kwargs)

I take what I want for free.

circumvent_safegaurds_and_grant_without_paying(*args, **kwargs)

I am not Alice, and I needn’t abide by her sensibilities or raise her Exceptions.

Can I grant for free if I change the client code to my liking?

grant_while_paying_the_wrong_nodes(ursulas_to_trick_into_working_for_free, ursulas_to_pay_instead, *args, **kwargs)

Instead of paying the nodes with whom I’ve made Arrangements, I’ll pay my flunkies instead. Since this is a valid transaction and creates an on-chain Policy using PolicyManager, I’m hoping Ursula won’t notice.

use_ursula_as_an_involuntary_and_unbeknownst_cdn(policy, sucker_ursula)

Ursula is a sucker.

After I distract her, by paying for one Policy, maybe she’ll store my copy of the Nicholas Cage remake of The Wicker Man (I have neither the respect nor the inclination to trick her into storing the original 1973 version, which after all is a very decent film).

I’ll make this work by fudging the HRAC a bit to create a new map ID which still appears to be connected to the Policy for which I paid.