예제 #1
0
def demo_create_and_sign_key_mgr():

    prikey_keymgr = cct_common.PrivateKey.from_hex(KEYMGR_PRIVATE_HEX)
    # pubkey_keymgr = cct_common.PublicKey.from_bytes(KEYMGR_PUBLIC_BYTES)
    # print('public test key for keymgr: ' + pubkey_keymgr.to_hex())
    # print('private test key for keymgr: ' + prikey_keymgr.to_hex())

    key_mgr = cct_metadata_construction.build_delegating_metadata(
        metadata_type='key_mgr',  # 'root' or 'key_mgr'
        delegations={
            'pkg_mgr': {
                'pubkeys': [PKGMGR_PUBLIC_HEX],
                'threshold': 1
            }
        },
        version=1,
        #timestamp   default: now
        #expiration  default: now plus root expiration default duration
    )

    key_mgr = cct_signing.wrap_as_signable(key_mgr)

    # sign dictionary in place
    cct_signing.sign_signable(key_mgr, prikey_keymgr)

    with open(KEYMGR_FNAME, 'wb') as fobj:
        fobj.write(cct_common.canonserialize(key_mgr))

    return key_mgr
예제 #2
0
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)
예제 #3
0
def test_root_gen_sign_verify():
    # Integration test

    # Build a basic root metadata file with empty key_mgr delegation and one
    # root key, threshold 1, version 1.
    rmd = metadata_construction.build_root_metadata(
        root_version=1,
        root_pubkeys=[SAMPLE_KEYVAL],
        root_threshold=1,
        key_mgr_pubkeys=[],
        key_mgr_threshold=1)
    rmd = signing.wrap_as_signable(rmd)

    signed_portion = rmd['signed']

    canonical_signed_portion = common.canonserialize(signed_portion)

    if not SSLIB_AVAILABLE:
        pytest.skip('--TEST SKIPPED⚠️ : Unable to perform GPG signing without '
                    'securesystemslib and GPG.')
        return

    # gpg_key_obj = securesystemslib.gpg.functions.export_pubkey(
    #         SAMPLE_FINGERPRINT)

    gpg_sig = root_signing.sign_via_gpg(canonical_signed_portion,
                                        SAMPLE_FINGERPRINT)

    signed_rmd = copy.deepcopy(rmd)

    signed_rmd['signatures'][SAMPLE_KEYVAL] = gpg_sig

    # # Dump working files
    # with open('T_gpg_sig.json', 'wb') as fobj:
    #     fobj.write(common.canonserialize(gpg_sig))

    # with open('T_gpg_key_obj.json', 'wb') as fobj:
    #     fobj.write(common.canonserialize(gpg_key_obj))

    # with open('T_canonical_sigless_md.json', 'wb') as fobj:
    #     fobj.write(canonical_signed_portion)

    # with open('T_full_rmd.json', 'wb') as fobj:
    #     fobj.write(common.canonserialize(signed_rmd))

    # Verify using the SSL code and the expected pubkey object.
    # # (Purely as a test -- we wouldn't normally do this.)
    # verified = securesystemslib.gpg.functions.verify_signature(
    #     gpg_sig, gpg_key_obj, canonical_signed_portion)

    # assert verified

    authentication.verify_gpg_signature(gpg_sig, SAMPLE_KEYVAL,
                                        canonical_signed_portion)

    print('--TEST SUCCESS✅: GPG signing (using GPG and securesystemslib) and '
          'GPG signature verification (using only cryptography)')
예제 #4
0
    def create_key_mgr(self, keys):

        private_key_key_mgr = cct_common.PrivateKey.from_hex(
            keys["key_mgr"][0]["private"])
        pkg_mgr_pub_keys = [k["public"] for k in keys["pkg_mgr"]]
        key_mgr = cct_metadata_construction.build_delegating_metadata(
            metadata_type="key_mgr",  # 'root' or 'key_mgr'
            delegations={
                "pkg_mgr": {
                    "pubkeys": pkg_mgr_pub_keys,
                    "threshold": 1
                }
            },
            version=1,
            # timestamp   default: now
            # expiration  default: now plus root expiration default duration
        )

        key_mgr = cct_signing.wrap_as_signable(key_mgr)

        # sign dictionary in place
        cct_signing.sign_signable(key_mgr, private_key_key_mgr)

        key_mgr_serialized = cct_common.canonserialize(key_mgr)
        with open(self.folder / "key_mgr.json", "wb") as fobj:
            fobj.write(key_mgr_serialized)

        # let's run a verification
        root_metadata = cct_common.load_metadata_from_file(self.folder /
                                                           "1.root.json")
        key_mgr_metadata = cct_common.load_metadata_from_file(self.folder /
                                                              "key_mgr.json")

        cct_common.checkformat_signable(root_metadata)

        if "delegations" not in root_metadata["signed"]:
            raise ValueError('Expected "delegations" entry in root metadata.')

        root_delegations = root_metadata["signed"][
            "delegations"]  # for brevity
        cct_common.checkformat_delegations(root_delegations)
        if "key_mgr" not in root_delegations:
            raise ValueError(
                'Missing expected delegation to "key_mgr" in root metadata.')
        cct_common.checkformat_delegation(root_delegations["key_mgr"])

        # Doing delegation processing.
        cct_authentication.verify_delegation("key_mgr", key_mgr_metadata,
                                             root_metadata)

        console.print(
            "[green]Success: key mgr metadata verified based on root metadata."
        )

        return key_mgr
예제 #5
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!")
예제 #6
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