Example #1
0
    def test_metadata_root(self):
        root_path = os.path.join(
                self.repo_dir, 'metadata', 'root.json')
        root = Metadata.from_file(root_path)

        # Add a second key to root role
        root_key2 =  import_ed25519_publickey_from_file(
                    os.path.join(self.keystore_dir, 'root_key2.pub'))

        keyid = root_key2['keyid']
        key_metadata = format_keyval_to_metadata(
            root_key2['keytype'], root_key2['scheme'], root_key2['keyval'])

        # Assert that root does not contain the new key
        self.assertNotIn(keyid, root.signed.roles['root']['keyids'])
        self.assertNotIn(keyid, root.signed.keys)

        # Add new root key
        root.signed.add_key('root', keyid, key_metadata)

        # Assert that key is added
        self.assertIn(keyid, root.signed.roles['root']['keyids'])
        self.assertIn(keyid, root.signed.keys)

        # Remove the key
        root.signed.remove_key('root', keyid)

        # Assert that root does not contain the new key anymore
        self.assertNotIn(keyid, root.signed.roles['root']['keyids'])
        self.assertNotIn(keyid, root.signed.keys)
Example #2
0
 def from_securesystemslib_key(cls, key_dict: Dict[str, Any]) -> "Key":
     """
     Creates a Key object from a securesystemlib key dict representation
     removing the private key from keyval.
     """
     key_meta = sslib_keys.format_keyval_to_metadata(
         key_dict["keytype"],
         key_dict["scheme"],
         key_dict["keyval"],
     )
     return cls(
         key_dict["keyid"],
         key_meta["keytype"],
         key_meta["scheme"],
         key_meta["keyval"],
     )
Example #3
0
def _save_project_configuration(metadata_directory, targets_directory,
                                public_keys, prefix, threshold, layout_type,
                                project_name):
    """
  <Purpose>
    Persist the project's information to a file. The saved project information
    can later be loaded with Project.load_project().

  <Arguments>
    metadata_directory:
      Where the project's metadata is located.

    targets_directory:
      The location of the target files for this project.

    public_keys:
      A list containing the public keys for the project role.

    prefix:
      The project's prefix (if any.)

    threshold:
      The threshold value for the project role.

    layout_type:
      The layout type being used by the project, "flat" stands for separated
      targets and metadata directories, "repo-like" emulates the layout used
      by the repository tools

    project_name:
      The name given to the project, this sets the metadata filename so it
      matches the one stored in upstream.

  <Exceptions>
    securesystemslib.exceptions.FormatError are also expected if any of the arguments are malformed.

    OSError may rise if the metadata_directory/project.cfg file exists and
    is non-writeable

  <Side Effects>
    A 'project.cfg' configuration file is created or overwritten.

  <Returns>
    None.
  """

    # Schema check for the arguments.
    sslib_formats.PATH_SCHEMA.check_match(metadata_directory)
    sslib_formats.PATH_SCHEMA.check_match(prefix)
    sslib_formats.PATH_SCHEMA.check_match(targets_directory)
    formats.RELPATH_SCHEMA.check_match(project_name)

    cfg_file_directory = metadata_directory

    # Check whether the layout type is 'flat' or 'repo-like'.
    # If it is, the .cfg file should be saved in the previous directory.
    if layout_type == 'repo-like':
        cfg_file_directory = os.path.dirname(metadata_directory)
        junk, targets_directory = os.path.split(targets_directory)

    junk, metadata_directory = os.path.split(metadata_directory)

    # Can the file be opened?
    project_filename = os.path.join(cfg_file_directory, PROJECT_FILENAME)

    # Build the fields of the configuration file.
    project_config = {}
    project_config['prefix'] = prefix
    project_config['public_keys'] = {}
    project_config['metadata_location'] = metadata_directory
    project_config['targets_location'] = targets_directory
    project_config['threshold'] = threshold
    project_config['layout_type'] = layout_type
    project_config['project_name'] = project_name

    # Build a dictionary containing the actual keys.
    for key in public_keys:
        key_info = keydb.get_key(key)
        key_metadata = format_keyval_to_metadata(key_info['keytype'],
                                                 key_info['scheme'],
                                                 key_info['keyval'])
        project_config['public_keys'][key] = key_metadata

    # Save the actual file.
    with open(project_filename, 'wt', encoding='utf8') as fp:
        json.dump(project_config, fp)
Example #4
0
def _generate_and_write_ecdsa_keypair(filepath=None,
                                      password=None,
                                      prompt=False):
    """Generates ecdsa key pair and writes custom JSON-formatted keys to disk.

  If a password is passed or entered on the prompt, the private key is
  encrypted using AES-256 in CTR mode, with the password strengthened in
  PBKDF2-HMAC-SHA256.

  NOTE: The custom key format includes 'ecdsa-sha2-nistp256' as signing scheme.

  Arguments:
    filepath (optional): The path to write the private key to. If not passed,
        the key is written to CWD using the keyid as filename. The public key
        is written to the same path as the private key using the suffix '.pub'.
    password (optional): An encryption password.
    prompt (optional): A boolean indicating if the user should be prompted
        for an encryption password. If the user enters an empty password, the
        key is not encrypted.

  Raises:
    UnsupportedLibraryError: pyca/cryptography is not available.
    FormatError: Arguments are malformed.
    ValueError: An empty string is passed as 'password', or both a 'password'
        is passed and 'prompt' is true.
    StorageError: Key files cannot be written.

  Side Effects:
    Prompts user for a password if 'prompt' is True.
    Writes key files to disk.

  Returns:
    The private key filepath.

  """
    ecdsa_key = keys.generate_ecdsa_key()

    # Use passed 'filepath' or keyid as file name
    if not filepath:
        filepath = os.path.join(os.getcwd(), ecdsa_key['keyid'])

    formats.PATH_SCHEMA.check_match(filepath)

    password = _get_key_file_encryption_password(password, prompt, filepath)

    # Create intermediate directories as required
    util.ensure_parent_dir(filepath)

    # Use custom JSON format for ecdsa keys on-disk
    keytype = ecdsa_key['keytype']
    keyval = ecdsa_key['keyval']
    scheme = ecdsa_key['scheme']
    ecdsakey_metadata_format = keys.format_keyval_to_metadata(keytype,
                                                              scheme,
                                                              keyval,
                                                              private=False)

    # Write public key to <filepath>.pub
    file_object = tempfile.TemporaryFile()
    file_object.write(json.dumps(ecdsakey_metadata_format).encode('utf-8'))
    util.persist_temp_file(file_object, filepath + '.pub')

    # Encrypt private key if we have a password, store as JSON string otherwise
    if password is not None:
        ecdsa_key = keys.encrypt_key(ecdsa_key, password)
    else:
        ecdsa_key = json.dumps(ecdsa_key)

    # Write private key to <filepath>
    file_object = tempfile.TemporaryFile()
    file_object.write(ecdsa_key.encode('utf-8'))
    util.persist_temp_file(file_object, filepath)

    return filepath