Пример #1
0
def test_keystore_persistence(tmpdir):
    """Regression test for keystore file persistence"""
    keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
    keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
    path = keystore.keystore_path
    del keystore
    assert path.exists()
Пример #2
0
def test_restore_keystore_from_mnemonic(tmpdir, mocker):

    # Setup
    spy = mocker.spy(Mnemonic, 'generate')

    # Decrypt post-generation
    keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
    keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
    mnemonic = Mnemonic(_MNEMONIC_LANGUAGE)
    words = spy.spy_return
    secret = bytes(mnemonic.to_entropy(words))
    keystore_path = keystore.keystore_path

    # remove local and disk references, simulating a
    # lost keystore or forgotten password.
    del keystore
    os.unlink(keystore_path)

    # prove the keystore is lost or missing
    assert not keystore_path.exists()
    with pytest.raises(Keystore.NotFound):
        _keystore = Keystore(keystore_path=keystore_path)

    # Restore with user-supplied words and a new password
    keystore = Keystore.restore(words=words, password='******')
    keystore.unlock(password='******')
    assert keystore._Keystore__secret == secret
Пример #3
0
def test_keystore_lock_unlock(tmpdir):
    keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)

    # locked by default
    assert not keystore.is_unlocked
    assert keystore._Keystore__secret is KEYSTORE_LOCKED

    # incorrect password
    with pytest.raises(Keystore.AuthenticationFailed):
        keystore.unlock('opensaysme')

    # unlock
    keystore.unlock(INSECURE_DEVELOPMENT_PASSWORD)
    assert keystore.is_unlocked
    assert keystore._Keystore__secret != KEYSTORE_LOCKED
    assert isinstance(keystore._Keystore__secret, bytes)

    # unlock when already unlocked
    keystore.unlock(INSECURE_DEVELOPMENT_PASSWORD)
    assert keystore.is_unlocked

    # incorrect password when already unlocked
    with pytest.raises(Keystore.AuthenticationFailed):
        keystore.unlock('opensaysme')

    # lock
    keystore.lock()
    assert not keystore.is_unlocked

    # lock when already locked
    keystore.lock()
    assert not keystore.is_unlocked
Пример #4
0
def test_unlock_nucypher_keystore_invalid_password(
        mocker, test_emitter, alice_blockchain_test_config, capsys, tmpdir,
        test_registry_source_manager):

    # Setup
    mocker.patch.object(passwords,
                        'secret_box_decrypt',
                        side_effect=SecretBoxAuthenticationError)
    mocker.patch.object(CharacterConfiguration,
                        'dev_mode',
                        return_value=False,
                        new_callable=mocker.PropertyMock)
    keystore = Keystore.generate(password=INSECURE_DEVELOPMENT_PASSWORD,
                                 keystore_dir=tmpdir)
    alice_blockchain_test_config.attach_keystore(keystore)

    # Test
    with pytest.raises(Keystore.AuthenticationFailed):
        unlock_nucypher_keystore(
            emitter=test_emitter,
            password=INSECURE_DEVELOPMENT_PASSWORD + 'typo',
            character_configuration=alice_blockchain_test_config)

    captured = capsys.readouterr()
    assert DECRYPTING_CHARACTER_KEYSTORE.format(
        name=alice_blockchain_test_config.NAME.capitalize()) in captured.out
Пример #5
0
def test_unlock_nucypher_keystore_dev_mode(mocker, test_emitter, capsys,
                                           alice_blockchain_test_config,
                                           tmpdir):

    # Setup
    unlock_spy = mocker.spy(Keystore, 'unlock')
    mocker.patch.object(CharacterConfiguration,
                        'dev_mode',
                        return_value=True,
                        new_callable=mocker.PropertyMock)
    keystore = Keystore.generate(password=INSECURE_DEVELOPMENT_PASSWORD,
                                 keystore_dir=tmpdir)
    alice_blockchain_test_config.attach_keystore(keystore)

    result = unlock_nucypher_keystore(
        emitter=test_emitter,
        password=INSECURE_DEVELOPMENT_PASSWORD,
        character_configuration=alice_blockchain_test_config)

    assert result
    output = capsys.readouterr().out
    message = DECRYPTING_CHARACTER_KEYSTORE.format(
        name=alice_blockchain_test_config.NAME.capitalize())
    assert message in output

    unlock_spy.assert_not_called()
Пример #6
0
def test_unlock_nucypher_keystore(mocker, test_emitter, capsys,
                                  alice_blockchain_test_config, patch_keystore,
                                  tmpdir):

    # Setup
    # Do not test "real" unlocking here, just the plumbing
    unlock_spy = mocker.patch.object(Keystore, 'unlock', return_value=True)
    mocker.patch.object(CharacterConfiguration,
                        'dev_mode',
                        return_value=False,
                        new_callable=mocker.PropertyMock)
    mocker.patch.object(Mnemonic, 'detect_language', return_value='english')
    keystore = Keystore.generate(password=INSECURE_DEVELOPMENT_PASSWORD,
                                 keystore_dir=tmpdir)
    alice_blockchain_test_config.attach_keystore(keystore)

    result = unlock_nucypher_keystore(
        emitter=test_emitter,
        password=INSECURE_DEVELOPMENT_PASSWORD,
        character_configuration=alice_blockchain_test_config)

    assert result
    captured = capsys.readouterr()
    message = DECRYPTING_CHARACTER_KEYSTORE.format(
        name=alice_blockchain_test_config.NAME.capitalize())
    assert message in captured.out

    unlock_spy.assert_called_once_with(password=INSECURE_DEVELOPMENT_PASSWORD)
Пример #7
0
def test_generate_alice_keystore(temp_dir_path):

    keystore = Keystore.generate(password=INSECURE_DEVELOPMENT_PASSWORD,
                                 keystore_dir=temp_dir_path)

    with pytest.raises(Keystore.Locked):
        _dec_keypair = keystore.derive_crypto_power(DecryptingPower).keypair

    keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
    assert keystore.derive_crypto_power(DecryptingPower).keypair

    label = b'test'

    delegating_power = keystore.derive_crypto_power(DelegatingPower)
    delegating_pubkey = delegating_power.get_pubkey_from_label(label)

    bob_pubkey = SecretKey.random().public_key()
    signer = Signer(SecretKey.random())
    delegating_pubkey_again, _kfrags = delegating_power.generate_kfrags(
        bob_pubkey, signer, label, threshold=2, shares=3)

    assert delegating_pubkey == delegating_pubkey_again

    another_delegating_power = keystore.derive_crypto_power(DelegatingPower)
    another_delegating_pubkey = another_delegating_power.get_pubkey_from_label(
        label)

    assert delegating_pubkey == another_delegating_pubkey
Пример #8
0
def test_initialize_ursula_defaults(click_runner, mocker, tmpdir):

    # Mock out filesystem writes
    mocker.patch.object(UrsulaConfiguration, 'initialize', autospec=True)
    mocker.patch.object(UrsulaConfiguration,
                        'to_configuration_file',
                        autospec=True)

    # Mock Keystore init
    keystore = Keystore.generate(keystore_dir=tmpdir,
                                 password=INSECURE_DEVELOPMENT_PASSWORD)
    mocker.patch.object(CharacterConfiguration,
                        'keystore',
                        return_value=keystore,
                        new_callable=PropertyMock)

    # Use default ursula init args
    init_args = ('ursula', 'init', '--network', TEMPORARY_DOMAIN,
                 '--federated-only')

    user_input = YES_ENTER + FAKE_PASSWORD_CONFIRMED
    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 input=user_input,
                                 catch_exceptions=False)
    assert result.exit_code == 0

    # REST Host
    assert "Is this the public-facing address of Ursula? " in result.output

    # Auth
    assert COLLECT_NUCYPHER_PASSWORD in result.output, 'WARNING: User was not prompted for password'
    assert 'Repeat for confirmation:' in result.output, 'User was not prompted to confirm password'
Пример #9
0
def test_default_character_configuration_preservation(
        configuration_class, testerchain, test_registry_source_manager,
        tmpdir):

    configuration_class.DEFAULT_CONFIG_ROOT = Path('/tmp')
    fake_address = '0xdeadbeef'
    network = TEMPORARY_DOMAIN

    expected_filename = f'{configuration_class.NAME}.{configuration_class._CONFIG_FILE_EXTENSION}'
    generated_filename = configuration_class.generate_filename()
    assert generated_filename == expected_filename
    expected_filepath = Path('/', 'tmp', generated_filename)

    if expected_filepath.exists():
        expected_filepath.unlink()
    assert not expected_filepath.exists()

    if configuration_class == StakeHolderConfiguration:
        # special case for defaults
        character_config = StakeHolderConfiguration(
            provider_uri=testerchain.provider_uri, domain=network)

    elif configuration_class == UrsulaConfiguration:
        # special case for rest_host & dev mode
        # use keystore
        keystore = Keystore.generate(password=INSECURE_DEVELOPMENT_PASSWORD,
                                     keystore_dir=tmpdir)
        keystore.signing_public_key = SecretKey.random().public_key()
        character_config = configuration_class(checksum_address=fake_address,
                                               domain=network,
                                               rest_host=MOCK_IP_ADDRESS,
                                               keystore=keystore)

    else:
        character_config = configuration_class(checksum_address=fake_address,
                                               domain=network)

    generated_filepath = character_config.generate_filepath()
    assert generated_filepath == expected_filepath

    written_filepath = character_config.to_configuration_file()
    assert written_filepath == expected_filepath
    assert written_filepath.exists()

    try:
        # Read
        with open(character_config.filepath, 'r') as f:
            contents = f.read()

        # Restore from JSON file
        restored_configuration = configuration_class.from_configuration_file()
        assert character_config.serialize(
        ) == restored_configuration.serialize()

        # File still exists after reading
        assert written_filepath.exists()

    finally:
        if expected_filepath.exists():
            expected_filepath.unlink()
Пример #10
0
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)
    parent_skf = SecretKeyFactory.from_secure_randomness(keystore._Keystore__secret)
    child_skf = parent_skf.make_factory(_DELEGATING_INFO)
    assert delegating_power._DelegatingPower__secret_key_factory.to_secret_bytes() == child_skf.to_secret_bytes()
    assert delegating_power._get_privkey_from_label(label=b'some-label')
Пример #11
0
def test_derive_hosting_power(tmpdir):
    keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
    keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
    hosting_power = keystore.derive_crypto_power(power_class=TLSHostingPower, host=LOOPBACK_ADDRESS)
    assert hosting_power.public_key().public_numbers()
    assert hosting_power.keypair.certificate.public_bytes(encoding=Encoding.PEM)
    rederived_hosting_power = keystore.derive_crypto_power(power_class=TLSHostingPower, host=LOOPBACK_ADDRESS)
    assert hosting_power.public_key().public_numbers() == rederived_hosting_power.public_key().public_numbers()
Пример #12
0
def test_keystore_generation_defaults(tmp_path_factory):

    # Setup
    parent = Path(tmp_path_factory.mktemp('test-keystore-'))
    parent.touch(exist_ok=True)

    # Test
    keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=parent)
    assert not keystore.is_unlocked        # defaults to locked
    assert keystore._Keystore__secret is KEYSTORE_LOCKED
    assert parent in keystore.keystore_path.parents  # created in the correct directory
Пример #13
0
    def write_keystore(self,
                       password: str,
                       key_material: Optional[bytes] = None,
                       interactive: bool = True) -> Keystore:
        if key_material:
            self.__keystore = Keystore.import_secure(
                key_material=key_material,
                password=password,
                keystore_dir=self.keystore_dir)
        else:
            if interactive:
                self.__keystore = Keystore.generate(
                    password=password,
                    keystore_dir=self.keystore_dir,
                    interactive=interactive)
            else:
                self.__keystore, _ = Keystore.generate(
                    password=password,
                    keystore_dir=self.keystore_dir,
                    interactive=interactive)

        return self.keystore
Пример #14
0
def test_tls_hosting_certificate_remains_the_same(temp_dir_path, mocker):
    keystore = Keystore.generate(password=INSECURE_DEVELOPMENT_PASSWORD,
                                 keystore_dir=temp_dir_path)
    keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)

    rest_port = 12345
    db_filepath = tempfile.mkdtemp()

    ursula = Ursula(federated_only=True,
                    start_learning_now=False,
                    keystore=keystore,
                    rest_host=LOOPBACK_ADDRESS,
                    rest_port=rest_port,
                    db_filepath=db_filepath,
                    domain=TEMPORARY_DOMAIN)

    assert ursula.keystore is keystore
    assert ursula.certificate == ursula._crypto_power.power_ups(
        TLSHostingPower).keypair.certificate

    original_certificate_bytes = ursula.certificate.public_bytes(
        encoding=Encoding.DER)
    ursula.disenchant()
    del ursula

    spy_rest_server_init = mocker.spy(ProxyRESTServer, '__init__')
    recreated_ursula = Ursula(federated_only=True,
                              start_learning_now=False,
                              keystore=keystore,
                              rest_host=LOOPBACK_ADDRESS,
                              rest_port=rest_port,
                              db_filepath=db_filepath,
                              domain=TEMPORARY_DOMAIN)

    assert recreated_ursula.keystore is keystore
    assert recreated_ursula.certificate.public_bytes(
        encoding=Encoding.DER) == original_certificate_bytes
    tls_hosting_power = recreated_ursula._crypto_power.power_ups(
        TLSHostingPower)
    spy_rest_server_init.assert_called_once_with(
        ANY,  # self
        rest_host=LOOPBACK_ADDRESS,
        rest_port=rest_port,
        rest_app=IsType(Flask),
        datastore=IsType(Datastore),
        hosting_power=tls_hosting_power)
    recreated_ursula.disenchant()
def test_characters_use_keystore(temp_dir_path):
    keystore = Keystore.generate(password=INSECURE_DEVELOPMENT_PASSWORD,
                                 keystore_dir=temp_dir_path)
    keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
    alice = Alice(federated_only=True,
                  start_learning_now=False,
                  keystore=keystore)
    Bob(federated_only=True, start_learning_now=False, keystore=keystore)
    Ursula(federated_only=True,
           start_learning_now=False,
           keystore=keystore,
           rest_host=LOOPBACK_ADDRESS,
           rest_port=12345,
           db_filepath=tempfile.mkdtemp(),
           domain=TEMPORARY_DOMAIN)
    alice.disenchant(
    )  # To stop Alice's publication threadpool.  TODO: Maybe only start it at first enactment?
Пример #16
0
def test_decrypt_keystore(tmpdir, mocker):

    # Setup
    spy = mocker.spy(Mnemonic, 'generate')

    # Decrypt post-generation
    keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
    keystore.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
    mnemonic = Mnemonic(_MNEMONIC_LANGUAGE)
    words = spy.spy_return
    secret = bytes(mnemonic.to_entropy(words))
    assert keystore._Keystore__secret == secret

    # Decrypt from keystore file
    keystore_path = keystore.keystore_path
    del words
    del keystore
    keystore = Keystore(keystore_path=keystore_path)
    keystore.unlock(INSECURE_DEVELOPMENT_PASSWORD)
    assert keystore._Keystore__secret == secret
Пример #17
0
def test_initialize_alice_defaults(click_runner, mocker, custom_filepath,
                                   monkeypatch, blockchain_ursulas, tmpdir):
    monkeypatch.delenv(NUCYPHER_ENVVAR_KEYSTORE_PASSWORD, raising=False)

    # Mock out filesystem writes
    mocker.patch.object(AliceConfiguration, 'initialize', autospec=True)
    mocker.patch.object(AliceConfiguration,
                        'to_configuration_file',
                        autospec=True)
    mocker.patch.object(LocalFileBasedNodeStorage,
                        'all',
                        return_value=blockchain_ursulas)

    # Mock Keystore init
    keystore = Keystore.generate(keystore_dir=tmpdir,
                                 password=INSECURE_DEVELOPMENT_PASSWORD)
    mocker.patch.object(CharacterConfiguration,
                        'keystore',
                        return_value=keystore,
                        new_callable=PropertyMock)

    # Use default alice init args
    init_args = ('alice', 'init', '--network',
                 TEMPORARY_DOMAIN, '--config-root',
                 str(custom_filepath.absolute()), '--federated-only')
    result = click_runner.invoke(nucypher_cli,
                                 init_args,
                                 input=FAKE_PASSWORD_CONFIRMED,
                                 catch_exceptions=False)
    assert result.exit_code == 0

    # REST Host
    assert "nucypher alice run" in result.output

    # Auth
    assert COLLECT_NUCYPHER_PASSWORD in result.output, 'WARNING: User was not prompted for password'
    assert 'Repeat for confirmation:' in result.output, 'User was not prompted to confirm password'
Пример #18
0
def test_keystore_invalid_password(tmpdir):
    with pytest.raises(InvalidPassword):
        _keystore = Keystore.generate('short', keystore_dir=tmpdir)
Пример #19
0
def test_keystore_generate_report_interactive_false(tmpdir):
    _keystore, words = Keystore.generate(
        INSECURE_DEVELOPMENT_PASSWORD,
        keystore_dir=tmpdir,
        interactive=False)
    assert len(words.split(" ")) == 24
Пример #20
0
def test_keystore_derive_crypto_power_without_unlock(tmpdir):
    keystore = Keystore.generate(INSECURE_DEVELOPMENT_PASSWORD, keystore_dir=tmpdir)
    with pytest.raises(Keystore.Locked):
        keystore.derive_crypto_power(power_class=DecryptingPower)
Пример #21
0
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 bytes(decrypting_power.public_key()).hex()
    assert decrypting_power.keypair.fingerprint()