Exemplo n.º 1
0
def select_card(emitter, card_identifier: str) -> Card:
    if not card_identifier:
        cards = []
        for filename in os.listdir(Card.CARD_DIR):
            filepath = Card.CARD_DIR / filename
            card = Card.load(filepath=filepath)
            cards.append(card)
        paint_cards(emitter=emitter, cards=cards, as_table=True)
        selection = click.prompt('Select card',
                                 type=click.IntRange(0, len(cards)))
        card = cards[selection]
    else:
        card = Card.load(identifier=card_identifier)
    return card
Exemplo n.º 2
0
def retrieve(general_config,
             character_options,
             config_file,
             label,
             policy_encrypting_key,
             alice_verifying_key,
             message_kit,
             ipfs,
             alice,
             force):
    """Obtain plaintext from encrypted data, if access was granted."""

    # Setup
    emitter = setup_emitter(general_config)
    BOB = character_options.create_character(emitter, config_file)

    if ipfs:
        import ipfshttpclient
        # TODO: #2108
        emitter.message(f"Connecting to IPFS Gateway {ipfs}")
        ipfs_client = ipfshttpclient.connect(ipfs)
        cid = message_kit  # Understand the message kit value as an IPFS hash.
        raw_message_kit = ipfs_client.cat(cid)  # cat the contents at the hash reference
        emitter.message(f"Downloaded message kit from IPFS (CID {cid})", color='green')
        message_kit = raw_message_kit.decode()  # cast to utf-8

    if not alice_verifying_key:
        if alice:  # from storage
            card = Card.load(identifier=alice)
            if card.character is not Alice:
                emitter.error('Grantee card is not an Alice.')
                raise click.Abort
            alice_verifying_key = card.verifying_key.hex()
            emitter.message(f'{card.nickname or ("Alice #"+card.id.hex())}\n'
                            f'Verifying Key  | {card.verifying_key.hex()}',
                            color='green')
            if not force:
                click.confirm('Is this the correct Granter (Alice)?', abort=True)
        else:  # interactive
            alice_verifying_key = click.prompt("Enter Alice's verifying key")

    # Request
    bob_request_data = {
        'label': label,
        'policy_encrypting_key': policy_encrypting_key,
        'alice_verifying_key': alice_verifying_key,
        'message_kit': message_kit,
    }

    response = BOB.controller.retrieve(request=bob_request_data)
    return response
Exemplo n.º 3
0
def _list():
    """Show all character cards"""
    emitter = StdoutEmitter()
    if not Card.CARD_DIR.is_dir():
        Card.CARD_DIR.mkdir()
    card_filepaths = list(Card.CARD_DIR.iterdir())
    if not card_filepaths:
        emitter.error(
            f'No cards found at {Card.CARD_DIR}.  '
            f"To create one run 'nucypher {contacts.name} {create.name}'.")
    cards = list()
    for filename in card_filepaths:
        card = Card.load(filepath=Card.CARD_DIR / filename)
        cards.append(card)
    paint_cards(emitter=emitter, cards=cards, as_table=True)
Exemplo n.º 4
0
def _list():
    """Show all character cards"""
    emitter = StdoutEmitter()
    card_directory = Card.CARD_DIR
    try:
        card_filepaths = os.listdir(card_directory)
    except FileNotFoundError:
        os.mkdir(Card.CARD_DIR)
        card_filepaths = os.listdir(card_directory)
    if not card_filepaths:
        emitter.error(
            f'No cards found at {card_directory}.  '
            f"To create one run 'nucypher {contacts.name} {create.name}'.")
    cards = list()
    for filename in card_filepaths:
        card = Card.load(filepath=Card.CARD_DIR / filename)
        cards.append(card)
    paint_cards(emitter=emitter, cards=cards, as_table=True)
Exemplo n.º 5
0
def collect_keys_from_card(emitter: StdoutEmitter, card_identifier: str,
                           force: bool):
    emitter.message(f"Searching contacts for {card_identifier}\n",
                    color='yellow')
    card = Card.load(identifier=card_identifier)

    if card.character is not Bob:
        emitter.error('Grantee card is not a Bob.')
        raise click.Abort
    paint_single_card(emitter=emitter, card=card)

    if not force:
        click.confirm('Is this the correct grantee (Bob)?', abort=True)

    bob_encrypting_key = bytes(card.encrypting_key).hex()
    bob_verifying_key = bytes(card.verifying_key).hex()
    public_keys = PublicKeys(encrypting_key=bob_encrypting_key,
                             verifying_key=bob_verifying_key)
    return public_keys
Exemplo n.º 6
0
def retrieve_and_decrypt(general_config, character_options, config_file,
                         alice_verifying_key, treasure_map, message_kit, ipfs,
                         alice, decode, force):
    """Obtain plaintext from encrypted data, if access was granted."""
    # 'message_kit' is a required and a "multiple" value click option  - the option name was kept singular so that
    # it makes sense when specifying many of them i.e. `--message-kit <message_kit_1> --message-kit <message_kit_2> ...`
    message_kits = list(message_kit)

    # Setup
    emitter = setup_emitter(general_config)
    BOB = character_options.create_character(emitter,
                                             config_file,
                                             json_ipc=general_config.json_ipc)

    if not (bool(alice_verifying_key) ^ bool(alice)):
        message = f"Pass either '--alice_verifying_key' or '--alice'; " \
                  f"got {'both' if alice_verifying_key else 'neither'}"
        raise click.BadOptionUsage(
            option_name='--alice_verifying_key, --alice', message=message)

    if not alice_verifying_key:
        if alice:  # from storage
            card = Card.load(identifier=alice)
            if card.character is not Alice:
                emitter.error('Grantee card is not an Alice.')
                raise click.Abort
            alice_verifying_key = bytes(card.verifying_key).hex()
            emitter.message(
                f'{card.nickname or ("Alice #"+card.id.hex())}\n'
                f'Verifying Key  | {bytes(card.verifying_key).hex()}',
                color='green')
            if not force:
                click.confirm('Is this the correct Granter (Alice)?',
                              abort=True)

    if ipfs:
        # '--message_kit' option was repurposed to specify ipfs cids (#2098)
        cids = []
        for cid in message_kits:
            cids.append(cid)

        # populate message_kits list with actual message_kits
        message_kits = []
        import ipfshttpclient
        # TODO: #2108
        emitter.message(f"Connecting to IPFS Gateway {ipfs}")
        ipfs_client = ipfshttpclient.connect(ipfs)
        for cid in cids:
            raw_message_kit = ipfs_client.cat(
                cid)  # cat the contents at the hash reference
            emitter.message(f"Downloaded message kit from IPFS (CID {cid})",
                            color='green')
            message_kit = raw_message_kit.decode()  # cast to utf-8
            message_kits.append(message_kit)

    # Request
    bob_request_data = {
        'alice_verifying_key': alice_verifying_key,
        'message_kits': message_kits,
        'encrypted_treasure_map': treasure_map
    }

    response = BOB.controller.retrieve_and_decrypt(request=bob_request_data)
    if decode:
        messages = list(
            [b64decode(r).decode() for r in response['cleartexts']])
        emitter.echo('----------Messages----------')
        for message in messages:
            emitter.echo(message)
    return response
Exemplo n.º 7
0
def retrieve(general_config,
             character_options,
             config_file,
             label,
             policy_encrypting_key,
             alice_verifying_key,
             message_kit,
             ipfs,
             alice,
             decode,
             force):
    """Obtain plaintext from encrypted data, if access was granted."""

    # Setup
    emitter = setup_emitter(general_config)
    BOB = character_options.create_character(emitter, config_file, json_ipc=general_config.json_ipc)

    if not message_kit:
        if ipfs:
            prompt = "Enter IPFS CID for encrypted data"
        else:
            prompt = "Enter encrypted data (base64)"
        message_kit = click.prompt(prompt, type=click.STRING)

    if ipfs:
        import ipfshttpclient
        # TODO: #2108
        emitter.message(f"Connecting to IPFS Gateway {ipfs}")
        ipfs_client = ipfshttpclient.connect(ipfs)
        cid = message_kit  # Understand the message kit value as an IPFS hash.
        raw_message_kit = ipfs_client.cat(cid)  # cat the contents at the hash reference
        emitter.message(f"Downloaded message kit from IPFS (CID {cid})", color='green')
        message_kit = raw_message_kit.decode()  # cast to utf-8

    if not alice_verifying_key:
        if alice:  # from storage
            card = Card.load(identifier=alice)
            if card.character is not Alice:
                emitter.error('Grantee card is not an Alice.')
                raise click.Abort
            alice_verifying_key = bytes(card.verifying_key).hex()
            emitter.message(f'{card.nickname or ("Alice #"+card.id.hex())}\n'
                            f'Verifying Key  | {bytes(card.verifying_key).hex()}',
                            color='green')
            if not force:
                click.confirm('Is this the correct Granter (Alice)?', abort=True)
        else:  # interactive
            alice_verifying_key = click.prompt("Enter Alice's verifying key", click.STRING)

    if not force:
        if not policy_encrypting_key:
            policy_encrypting_key = click.prompt("Enter policy public key", type=click.STRING)

        if not label:
            label = click.prompt("Enter label to retrieve", type=click.STRING)

    # Request
    bob_request_data = {
        'label': label,
        'policy_encrypting_key': policy_encrypting_key,
        'alice_verifying_key': alice_verifying_key,
        'message_kit': message_kit,
    }

    response = BOB.controller.retrieve(request=bob_request_data)
    if decode:
        messages = list([b64decode(r).decode() for r in response['cleartexts']])
        emitter.echo('----------Messages----------')
        for message in messages:
            emitter.echo(message)
    return response
Exemplo n.º 8
0
def grant(general_config,
          bob,
          bob_encrypting_key,
          bob_verifying_key,
          label,
          value,
          rate,
          expiration,
          m, n,
          character_options,
          config_file,
          force):
    """Create and enact an access policy for some Bob. """

    # Setup
    emitter = setup_emitter(general_config)
    ALICE = character_options.create_character(emitter, config_file, general_config.json_ipc)

    # Policy option validation
    if ALICE.federated_only:
        if any((value, rate)):
            message = "Can't use --value or --rate with a federated Alice."
            raise click.BadOptionUsage(option_name="--value, --rate", message=message)
    elif bool(value) and bool(rate):
        raise click.BadOptionUsage(option_name="--rate", message="Can't use --value if using --rate")

    # Grantee selection
    if bob and any((bob_encrypting_key, bob_verifying_key)):
        message = '--bob cannot be used with --bob-encrypting-key or --bob-veryfying key'
        raise click.BadOptionUsage(option_name='--bob', message=message)

    if bob:
        card = Card.load(identifier=bob)
        if card.character is not Bob:
            emitter.error('Grantee card is not a Bob.')
            raise click.Abort
        paint_single_card(emitter=emitter, card=card)
        if not force:
            click.confirm('Is this the correct grantee (Bob)?', abort=True)
        bob_encrypting_key = card.encrypting_key.hex()
        bob_verifying_key = card.verifying_key.hex()

    # Interactive collection follows:
    # TODO: Extricate to support modules
    # - Disclaimer
    # - Label
    # - Expiration Date & Time
    # - M of N
    # - Policy Value (ETH)

    # Policy Expiration
    # TODO: Remove this line when the time is right.
    paint_probationary_period_disclaimer(emitter)

    # Label
    if not label:
        label = click.prompt(f'Enter label to grant Bob {bob_verifying_key[:8]}', type=click.STRING)

    if not force and not expiration:
        if ALICE.duration_periods:
            # TODO: use a default in days or periods?
            expiration = maya.now() + timedelta(days=ALICE.duration_periods)  # default
            if not click.confirm(f'Use default policy duration (expires {expiration})?'):
                expiration = click.prompt('Enter policy expiration datetime', type=click.DateTime())
        else:
            # No policy duration default default available; Go interactive
            expiration = click.prompt('Enter policy expiration datetime', type=click.DateTime())

    # TODO: Remove this line when the time is right.
    enforce_probationary_period(emitter=emitter, expiration=expiration)

    # Policy Threshold and Shares
    if not n:
        n = ALICE.n
        if not force and not click.confirm(f'Use default value for N ({n})?', default=True):
            n = click.prompt('Enter total number of shares (N)', type=click.INT)
    if not m:
        m = ALICE.m
        if not force and not click.confirm(f'Use default value for M ({m})?', default=True):
            m = click.prompt('Enter threshold (M)', type=click.IntRange(1, n))

    # Policy Value
    policy_value_provided = bool(value) or bool(rate)
    if not ALICE.federated_only and not policy_value_provided:
        rate = ALICE.default_rate  # TODO #1709 - Fine tuning and selection of default rates
        if not force:
            default_gwei = Web3.fromWei(rate, 'gwei')
            prompt = "Confirm rate of {node_rate} gwei ({total_rate} gwei per period)?"
            if not click.confirm(prompt.format(node_rate=default_gwei, total_rate=default_gwei*n), default=True):
                interactive_rate = click.prompt('Enter rate per period in gwei', type=GWEI)
                # TODO: Validate interactively collected rate (#1709)
                click.confirm(prompt.format(node_rate=rate, total_rate=rate*n), default=True, abort=True)
                rate = Web3.toWei(interactive_rate, 'gwei')

    # Request
    grant_request = {
        'bob_encrypting_key': bob_encrypting_key,
        'bob_verifying_key': bob_verifying_key,
        'label': label,
        'm': m,
        'n': n,
        'expiration': expiration,
    }
    if not ALICE.federated_only:
        if value:
            grant_request['value'] = value
        elif rate:
            grant_request['rate'] = rate  # in wei

    if not force and not general_config.json_ipc:
        confirm_staged_grant(emitter=emitter, grant_request=grant_request)
    emitter.echo(f'Granting Access to {bob_verifying_key[:8]}', color='yellow')
    return ALICE.controller.grant(request=grant_request)