def test_generate_and_write_ecdsa_keypair(self):

        # Test normal case.
        temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
        test_keypath = os.path.join(temporary_directory, 'ecdsa_key')

        returned_path = interface.generate_and_write_ecdsa_keypair(
            test_keypath, password='******')
        self.assertTrue(os.path.exists(test_keypath))
        self.assertTrue(os.path.exists(test_keypath + '.pub'))
        self.assertEqual(returned_path, test_keypath)

        # Ensure the generated key files are importable.
        imported_pubkey = \
          interface.import_ecdsa_publickey_from_file(test_keypath + '.pub')
        self.assertTrue(
            securesystemslib.formats.ECDSAKEY_SCHEMA.matches(imported_pubkey))

        imported_privkey = \
          interface.import_ecdsa_privatekey_from_file(test_keypath, 'pw')
        self.assertTrue(
            securesystemslib.formats.ECDSAKEY_SCHEMA.matches(imported_privkey))

        # Test for a default filepath.  If 'filepath' is not given, the key's
        # KEYID is used as the filename.  The key is saved to the current working
        # directory.
        default_keypath = interface.generate_and_write_ecdsa_keypair(
            password='******')
        self.assertTrue(os.path.exists(default_keypath))
        self.assertTrue(os.path.exists(default_keypath + '.pub'))

        written_key = interface.import_ecdsa_publickey_from_file(
            default_keypath + '.pub')
        self.assertEqual(written_key['keyid'],
                         os.path.basename(default_keypath))

        os.remove(default_keypath)
        os.remove(default_keypath + '.pub')

        # Test improperly formatted arguments.
        self.assertRaises(securesystemslib.exceptions.FormatError,
                          interface.generate_and_write_ecdsa_keypair,
                          3,
                          password='******')
        self.assertRaises(securesystemslib.exceptions.FormatError,
                          interface.generate_and_write_ecdsa_keypair,
                          test_keypath,
                          password=3)
  def test_generate_and_write_ed25519_keypair(self):

    # Test normal case.
    temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
    test_keypath = os.path.join(temporary_directory, 'ecdsa_key')

    interface.generate_and_write_ecdsa_keypair(test_keypath, password='******')
    self.assertTrue(os.path.exists(test_keypath))
    self.assertTrue(os.path.exists(test_keypath + '.pub'))

    # Ensure the generated key files are importable.
    imported_pubkey = \
      interface.import_ecdsa_publickey_from_file(test_keypath + '.pub')
    self.assertTrue(securesystemslib.formats.ECDSAKEY_SCHEMA.matches(imported_pubkey))

    imported_privkey = \
      interface.import_ecdsa_privatekey_from_file(test_keypath, 'pw')
    self.assertTrue(securesystemslib.formats.ECDSAKEY_SCHEMA.matches(imported_privkey))


    # Test improperly formatted arguments.
    self.assertRaises(securesystemslib.exceptions.FormatError,
        interface.generate_and_write_ecdsa_keypair, 3, password='******')
    self.assertRaises(securesystemslib.exceptions.FormatError,
        interface.generate_and_write_ecdsa_keypair, test_keypath, password=3)
示例#3
0
    def test_import_ecdsa_publickey_from_file(self):
        # Test normal case.
        # Generate ecdsa keys that can be imported.
        temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
        ecdsa_keypath = os.path.join(temporary_directory, 'ecdsa_key')
        interface.generate_and_write_ecdsa_keypair(ecdsa_keypath,
                                                   password='******')

        imported_ecdsa_key = \
          interface.import_ecdsa_publickey_from_file(ecdsa_keypath + '.pub')
        self.assertTrue(
            securesystemslib.formats.ECDSAKEY_SCHEMA.matches(
                imported_ecdsa_key))

        # Test improperly formatted argument.
        self.assertRaises(securesystemslib.exceptions.FormatError,
                          interface.import_ecdsa_publickey_from_file, 3)

        # Test invalid argument.
        # Non-existent key file.
        nonexistent_keypath = os.path.join(temporary_directory,
                                           'nonexistent_keypath')
        self.assertRaises(securesystemslib.exceptions.StorageError,
                          interface.import_ecdsa_publickey_from_file,
                          nonexistent_keypath)

        # Invalid key file argument.
        invalid_keyfile = os.path.join(temporary_directory, 'invalid_keyfile')
        with open(invalid_keyfile, 'wb') as file_object:
            file_object.write(b'bad keyfile')

        self.assertRaises(securesystemslib.exceptions.Error,
                          interface.import_ecdsa_publickey_from_file,
                          invalid_keyfile)

        # Invalid public key imported (contains unexpected keytype.)
        keytype = imported_ecdsa_key['keytype']
        keyval = imported_ecdsa_key['keyval']
        scheme = imported_ecdsa_key['scheme']

        ecdsakey_metadata_format = \
          securesystemslib.keys.format_keyval_to_metadata(keytype,
              scheme, keyval, private=False)

        ecdsakey_metadata_format['keytype'] = 'invalid_keytype'
        with open(ecdsa_keypath + '.pub', 'wb') as file_object:
            file_object.write(
                json.dumps(ecdsakey_metadata_format).encode('utf-8'))

        self.assertRaises(securesystemslib.exceptions.FormatError,
                          interface.import_ecdsa_publickey_from_file,
                          ecdsa_keypath + '.pub')
示例#4
0
def create_and_set_keys(keystore_dir, repo_obj):
    for rolename in ('root', 'timestamp', 'snapshot', 'targets'):
        passphrase = os.environ.get('{}_PASSPHRASE'.format(rolename.upper()))
        if not passphrase:
            passphrase = get_password(
                prompt='Enter password for {}: '.format(rolename),
                confirm=True)

        private_keypath = str(get_private_keypath(keystore_dir, rolename))
        public_keypath = get_public_keypath(private_keypath)

        generate_and_write_ecdsa_keypair(private_keypath, password=passphrase)

        private = import_ecdsa_privatekey_from_file(private_keypath,
                                                    passphrase)
        public = import_ecdsa_publickey_from_file(public_keypath)

        role_obj = getattr(repo_obj, rolename)
        role_obj.load_signing_key(private)
        role_obj.add_verification_key(public)
    def test_ecdsa(self):
        """Test ecdsa key _generation and import interface functions. """
        # TEST: Generate default keys and import
        # Assert location and format
        fn_default = "default"
        fn_default_ret = _generate_and_write_ecdsa_keypair(filepath=fn_default)

        pub = import_ecdsa_publickey_from_file(fn_default + ".pub")
        priv = import_ecdsa_privatekey_from_file(fn_default)

        self.assertEqual(fn_default, fn_default_ret)
        self.assertTrue(ECDSAKEY_SCHEMA.matches(pub))
        self.assertTrue(PUBLIC_KEY_SCHEMA.matches(pub))
        self.assertTrue(ECDSAKEY_SCHEMA.matches(priv))
        # NOTE: There is no private key schema, at least check it has a value
        self.assertTrue(priv["keyval"]["private"])

        # TEST: Generate unencrypted keys with empty prompt
        # Assert importable with empty prompt password and without password
        fn_empty_prompt = "empty_prompt"
        with mock.patch("securesystemslib.interface.get_password",
                        return_value=""):
            _generate_and_write_ecdsa_keypair(filepath=fn_empty_prompt)
            import_ecdsa_privatekey_from_file(fn_empty_prompt, prompt=True)
        import_ecdsa_privatekey_from_file(fn_empty_prompt)

        # TEST: Generate keys with auto-filename, i.e. keyid
        # Assert filename is keyid
        fn_keyid = _generate_and_write_ecdsa_keypair()
        pub = import_ecdsa_publickey_from_file(fn_keyid + ".pub")
        priv = import_ecdsa_privatekey_from_file(fn_keyid)
        self.assertTrue(
            os.path.basename(fn_keyid) == pub["keyid"] == priv["keyid"])

        # TEST: Generate two key pairs with encrypted private keys using ...
        pw = "pw"
        fn_encrypted = "encrypted"
        fn_prompt = "prompt"
        # ...  a passed pw ...
        _generate_and_write_ecdsa_keypair(filepath=fn_encrypted, password=pw)
        with mock.patch("securesystemslib.interface.get_password",
                        return_value=pw):
            # ... and a prompted pw.
            _generate_and_write_ecdsa_keypair(filepath=fn_prompt, prompt=True)

            # Assert that both private keys are importable using the prompted pw ...
            import_ecdsa_privatekey_from_file(fn_prompt, prompt=True)
            import_ecdsa_privatekey_from_file(fn_encrypted, prompt=True)

        # ... and the passed pw.
        import_ecdsa_privatekey_from_file(fn_prompt, password=pw)
        import_ecdsa_privatekey_from_file(fn_encrypted, password=pw)

        # TEST: Import existing keys with encrypted private key (test regression)
        # Assert format
        pub = import_ecdsa_publickey_from_file(self.path_ecdsa + ".pub")
        priv = import_ecdsa_privatekey_from_file(self.path_ecdsa, "password")

        self.assertTrue(ECDSAKEY_SCHEMA.matches(pub))
        self.assertTrue(PUBLIC_KEY_SCHEMA.matches(pub))
        self.assertTrue(ECDSAKEY_SCHEMA.matches(priv))
        # NOTE: There is no private key schema, at least check it has a value
        self.assertTrue(priv["keyval"]["private"])

        # FIXME: Should 'import_ecdsa_publickey_from_file' be able to import a
        # an ed25519 public key? I think it should not, but it is:
        import_ecdsa_publickey_from_file(self.path_ed25519 + ".pub")
        self.assertTrue(ECDSAKEY_SCHEMA.matches(pub))

        # TEST: Generation errors
        for idx, (kwargs, err_msg) in enumerate([
                # Error on empty password
            ({
                "password": ""
            }, "encryption password must be 1 or more characters long"),
                # Error on 'password' and 'prompt=True'
            ({
                "password": pw,
                "prompt": True
            }, "passing 'password' and 'prompt=True' is not allowed")
        ]):

            with self.assertRaises(ValueError,
                                   msg="(row {})".format(idx)) as ctx:
                _generate_and_write_ecdsa_keypair(**kwargs)

            self.assertEqual(
                err_msg, str(ctx.exception),
                "expected: '{}' got: '{}' (row {})".format(
                    err_msg, ctx.exception, idx))

        # Error on bad argument format
        for idx, kwargs in enumerate([
            {
                "filepath": 123456
            },  # Not a string
            {
                "password": 123456
            },  # Not a string
            {
                "prompt": "not-a-bool"
            }
        ]):
            with self.assertRaises(FormatError, msg="(row {})".format(idx)):
                _generate_and_write_ecdsa_keypair(**kwargs)

        # TEST: Import errors

        # Error on public key import...
        for idx, (fn, err_msg) in enumerate([
                # Error on invalid json (custom key format)
            (fn_encrypted, "Cannot deserialize to a Python object"),
                # Error on invalid custom key format
            (self.path_no_key, "Missing key")
        ]):
            with self.assertRaises(Error, msg="(row {})".format(idx)) as ctx:
                import_ecdsa_publickey_from_file(fn)

            self.assertTrue(
                err_msg in str(ctx.exception),
                "expected: '{}' got: '{}' (row {})".format(
                    err_msg, ctx.exception, idx))

        # Error on private key import...
        for idx, (args, kwargs, err, err_msg) in enumerate([
                # Error on not an ecdsa private key
            ([self.path_ed25519], {}, Error,
             "Cannot deserialize to a Python object"),
                # Error on not encrypted
            ([fn_default], {
                "password": pw
            }, CryptoError, "Invalid encrypted file."),
                # Error on encrypted but no pw
            ([fn_encrypted], {}, Error, "Cannot deserialize to a Python object"
             ),
                # Error on encrypted but empty pw
            ([fn_encrypted], {
                "password": ""
            }, CryptoError, "Decryption failed."),
                # Error on encrypted but bad pw passed
            ([fn_encrypted], {
                "password": "******"
            }, CryptoError, "Decryption failed."),
                # Error on pw and prompt
            ([fn_default], {
                "password": pw,
                "prompt": True
            }, ValueError,
             "passing 'password' and 'prompt=True' is not allowed")
        ]):

            with self.assertRaises(err, msg="(row {})".format(idx)) as ctx:
                import_ecdsa_privatekey_from_file(*args, **kwargs)

            self.assertTrue(
                err_msg in str(ctx.exception),
                "expected: '{}' got: '{}' (row {})".format(
                    err_msg, ctx.exception, idx))

        # Error on encrypted but bad pw prompted
        err_msg = ("Decryption failed")
        with self.assertRaises(CryptoError) as ctx, mock.patch(
                "securesystemslib.interface.get_password",
                return_value="bad_pw"):
            import_ecdsa_privatekey_from_file(fn_encrypted, prompt=True)

        self.assertTrue(
            err_msg in str(ctx.exception),
            "expected: '{}' got: '{}'".format(err_msg, ctx.exception))

        # Error on bad path format
        with self.assertRaises(FormatError):
            import_ecdsa_publickey_from_file(123456)
        with self.assertRaises(FormatError):
            import_ecdsa_privatekey_from_file(123456)

        # Error on bad password format
        with self.assertRaises(FormatError):  # bad password
            import_ecdsa_privatekey_from_file(fn_default, password=123456)

        # Error on bad prompt format
        with self.assertRaises(FormatError):
            import_ecdsa_privatekey_from_file(fn_default, prompt="not-a-bool")