def test_verify_existing_root_md():

    # It's important that we are able to verify root metadata without anything
    # except old root metadata, so in particular we don't want to need the
    # full GPG public key object.  Ideally, we want only the Q value of the
    # key, but if we also need to retain the GPG key fingerprint (listed in the
    # signature itself), we can do that.....

    # with open('T_full_rmd.json', 'rb') as fobj:
    #     signed_rmd = json.load(fobj)
    #
    # gpg_sig = signed_rmd['signatures'][
    #     'bfbeb6554fca9558da7aa05c5e9952b7a1aa3995dede93f3bb89f0abecc7dc07']
    #
    # canonical_signed_portion = common.canonserialize(signed_rmd['signed'])
    #
    # with open('T_gpg_key_obj.json', 'rb') as fobj:
    #     gpg_key_obj = json.load(fobj)
    # q = gpg_key_obj['keyval']['public']['q']
    # fingerprint = gpg_key_obj['keyid']

    canonical_signed_portion = common.canonserialize(SAMPLE_ROOT_MD_CONTENT)

    # # First, try using securesystemslib's GPG signature verifier directly.
    # verified = securesystemslib.gpg.functions.verify_signature(
    #     SAMPLE_GPG_SIG,
    #     SAMPLE_GPG_KEY_OBJ,  # <-- We don't want conda to have to provide this.
    #     canonical_signed_portion)

    # assert verified

    # # Second, try it using my adapter, skipping a bit of ssl's process.
    # verified = root_signing.verify_gpg_sig_using_ssl(
    #         SAMPLE_GPG_SIG,
    #         SAMPLE_FINGERPRINT,
    #         SAMPLE_KEYVAL,
    #         canonical_signed_portion)

    # assert verified

    # Third, use internal code only.  (This is what we're actually going to
    # use in conda.)

    # Verify using verify_gpg_signature.
    authentication.verify_gpg_signature(
        # authentication.verify_gpg_signature(
        SAMPLE_GPG_SIG,
        SAMPLE_KEYVAL,
        canonical_signed_portion)

    print('--TEST SUCCESS✅: GPG signature verification without using GPG or '
          'securesystemslib')

    # Verify using verify_signable.
    authentication.verify_signable(SAMPLE_SIGNED_ROOT_MD, [SAMPLE_KEYVAL],
                                   1,
                                   gpg=True)
示例#2
0
    def create_root(self, keys):
        root_keys = keys["root"]

        root_pubkeys = [k["public"] for k in root_keys]
        key_mgr_pubkeys = [k["public"] for k in keys["key_mgr"]]

        root_version = 1

        root_md = cct_metadata_construction.build_root_metadata(
            root_pubkeys=root_pubkeys[0:1],
            root_threshold=1,
            root_version=root_version,
            key_mgr_pubkeys=key_mgr_pubkeys,
            key_mgr_threshold=1,
        )

        # Wrap the metadata in a signing envelope.
        root_md = cct_signing.wrap_as_signable(root_md)

        root_md_serialized_unsigned = cct_common.canonserialize(root_md)

        root_filepath = self.folder / f"{root_version}.root.json"
        print("Writing out: ", root_filepath)
        # Write unsigned sample root metadata.
        with open(root_filepath, "wb") as fout:
            fout.write(root_md_serialized_unsigned)

        # This overwrites the file with a signed version of the file.
        cct_root_signing.sign_root_metadata_via_gpg(
            root_filepath, root_keys[0]["fingerprint"])

        # Load untrusted signed root metadata.
        signed_root_md = cct_common.load_metadata_from_file(root_filepath)

        cct_authentication.verify_signable(signed_root_md,
                                           root_pubkeys,
                                           1,
                                           gpg=True)

        console.print("[green]Root metadata signed & verified!")
示例#3
0
def demo_root_signing_and_verifying_and_chaining():
    # Build sample root metadata.  ('metadata' -> 'md')
    root_md = cct_metadata_construction.build_root_metadata(
        root_pubkeys=[ROOT_PUBKEY_HEX],
        root_threshold=1,
        root_version=1,
        key_mgr_pubkeys=[KEYMGR_PUBLIC_HEX],
        key_mgr_threshold=1)

    # Wrap the metadata in a signing envelope.
    root_md = cct_signing.wrap_as_signable(root_md)

    root_md_serialized_unsigned = cct_common.canonserialize(root_md)

    print('\n-- Unsigned root metadata version 1 generated.\n')

    # # This is the part of the data over which signatures are constructed.
    # root_md_serialized_portion_to_sign = cct_common.canonserialize(
    #         root_md['signed'])

    # TODO: ✅ Format-validate constructed root metadata using checkformat
    #          function.

    if not os.path.exists('demo'):
        os.mkdir('demo')

    # Write unsigned sample root metadata.
    with open(ROOT_FNAME_V1, 'wb') as fobj:
        fobj.write(root_md_serialized_unsigned)
    print('\n-- Unsigned root metadata version 1 written.\n')

    # Sign sample root metadata.
    junk = input_func(
        'Preparing to request root signature.  Please plug in your '
        'YubiKey and prepare to put in your user PIN in a GPG dialog box. '
        ' When the YubiKey is plugged in and you are READY TO ENTER your '
        'pin, hit enter to begin.')

    # This overwrites the file with a signed version of the file.
    cct_root_signing.sign_root_metadata_via_gpg(ROOT_FNAME_V1,
                                                ROOT_PUBKEY_GPG_FINGERPRINT)
    cct_root_signing.sign_root_metadata_via_gpg(ROOT_FNAME_V1,
                                                ROOT_PUBKEY_GPG_FINGERPRINT)
    junk = input_func(
        '\n-- Root metadata v1 signed.  Next: load signed root v1.\n')

    # Load untrusted signed root metadata.
    signed_root_md = cct_common.load_metadata_from_file(ROOT_FNAME_V1)
    junk = input_func(
        '\n-- Signed root metadata v1 loaded.  Next: verify signed root v1\n')

    # Verify untrusted signed root metadata.  (Normally, one uses the prior
    # version of root, but here we're bootstrapping for the demo.  We'll verify
    # with a prior version lower down in this demo.)
    cct_authentication.verify_signable(signed_root_md, [ROOT_PUBKEY_HEX],
                                       1,
                                       gpg=True)
    junk = input_func(
        '\n-- Root metadata v1 fully verified.  Next: build root metadata v2.\n'
    )

    # Build sample second version of root metadata.  In this case, let's try
    # adding another authorized key and requiring signatures from both keys.
    root_md2 = cct_metadata_construction.build_root_metadata(
        root_pubkeys=[ROOT_PUBKEY_HEX, ROOT_PUBKEY_2_HEX],
        root_threshold=2,
        root_version=2,
        key_mgr_pubkeys=[KEYMGR_PUBLIC_HEX],
        key_mgr_threshold=1)

    # Wrap the version 2 metadata in a signing envelope, canonicalize it, and
    # serialize it to write to disk.
    root_md2 = cct_signing.wrap_as_signable(root_md2)
    root_md2 = cct_common.canonserialize(root_md2)

    # Write unsigned sample root metadata.
    with open(ROOT_FNAME_V2, 'wb') as fobj:
        fobj.write(root_md2)
    junk = input_func(
        '\n-- Unsigned root metadata version 2 generated and written.  Next: sign root v2\n'
    )

    # This overwrites the file with a signed version of the file.
    # We'll sign with both keys specified.
    cct_root_signing.sign_root_metadata_via_gpg(ROOT_FNAME_V2,
                                                ROOT_PUBKEY_GPG_FINGERPRINT)
    cct_root_signing.sign_root_metadata_via_gpg(ROOT_FNAME_V2,
                                                ROOT_PUBKEY_2_GPG_FINGERPRINT)
    junk = input_func(
        '\n-- Root metadata v2 signed.  Next: load and verify signed root v2 based on root v1 (root chaining).\n'
    )

    # Load the now-signed version from disk.
    signed_root_md2 = cct_common.load_metadata_from_file(ROOT_FNAME_V2)

    # Test root chaining (verifying v2 using v1)
    cct_authentication.verify_root(signed_root_md, signed_root_md2)
    print('\n-- Root metadata v2 fully verified based directly on Root '
          'metadata v1 (root chaining success)\n')

    print('\n-- Success. :)\n')

    # Build sample third version of root metadata.  In this case, let's reduce
    # the number of required keys to one.
    root_md3 = cct_metadata_construction.build_root_metadata(
        root_pubkeys=[ROOT_PUBKEY_HEX, ROOT_PUBKEY_2_HEX],
        root_threshold=1,
        root_version=3,
        key_mgr_pubkeys=[KEYMGR_PUBLIC_HEX],
        key_mgr_threshold=1)

    # Wrap the version 2 metadata in a signing envelope, canonicalize it, and
    # serialize it to write to disk.
    root_md3 = cct_signing.wrap_as_signable(root_md3)
    root_md3 = cct_common.canonserialize(root_md3)

    # Write unsigned sample root metadata.
    with open(ROOT_FNAME_V3, 'wb') as fobj:
        fobj.write(root_md3)
    junk = input_func(
        '\n-- Unsigned root metadata version 2 generated and written.  Next: sign root v2\n'
    )

    # This overwrites the file with a signed version of the file.
    # We'll sign with both keys specified.
    cct_root_signing.sign_root_metadata_via_gpg(ROOT_FNAME_V3,
                                                ROOT_PUBKEY_GPG_FINGERPRINT)
    cct_root_signing.sign_root_metadata_via_gpg(ROOT_FNAME_V3,
                                                ROOT_PUBKEY_2_GPG_FINGERPRINT)
    junk = input_func(
        '\n-- Root metadata v2 signed.  Next: load and verify signed root v2 based on root v1 (root chaining).\n'
    )

    # Load the now-signed version from disk.
    signed_root_md3 = cct_common.load_metadata_from_file(ROOT_FNAME_V3)

    # Test root chaining (verifying v2 using v1)
    cct_authentication.verify_root(signed_root_md2, signed_root_md3)
    print('\n-- Root metadata v3 fully verified based directly on Root '
          'metadata v2 (root chaining success)\n')

    print('\n-- Success. :)\n')

    return signed_root_md, signed_root_md2, signed_root_md3