def test_sign_key_exportable(context, exportable): gpg_home2 = os.path.join(context.config['gpg_home'], "two") context.config['gpg_home'] = os.path.join(context.config['gpg_home'], "one") gpg = sgpg.GPG(context) gpg2 = sgpg.GPG(context, gpg_home=gpg_home2) my_fingerprint = KEYS_AND_FINGERPRINTS[0][1] my_keyid = KEYS_AND_FINGERPRINTS[0][0] # import my keys for suffix in (".sec", ".pub"): with open("{}{}".format(KEYS_AND_FINGERPRINTS[0][2], suffix), "r") as fh: contents = fh.read() sgpg.import_key(gpg, contents) # create gpg.conf's sgpg.create_gpg_conf(context.config['gpg_home'], my_fingerprint=my_fingerprint) sgpg.create_gpg_conf(gpg_home2, my_fingerprint=my_fingerprint) sgpg.check_ownertrust(context) sgpg.check_ownertrust(context, gpg_home=gpg_home2) # generate a new key fingerprint = sgpg.generate_key(gpg, "one", "one", "one", key_length=GENERATE_KEY_SMALLER_KEY_SIZE) # sign it, exportable signature is `exportable` sgpg.sign_key(context, fingerprint, signing_key=my_fingerprint, exportable=exportable) # export my privkey and import it in gpg_home2 priv_key = sgpg.export_key(gpg, my_fingerprint, private=True) sgpg.import_key(gpg2, priv_key) # export both pubkeys and import in gpg_home2 for fp in (my_fingerprint, fingerprint): pub_key = sgpg.export_key(gpg, fp) sgpg.import_key(gpg2, pub_key) # check sigs on `fingerprint` key. If exportable, we're good. If not exportable, # it'll throw expected = {'sig_keyids': [my_keyid]} if exportable: sgpg.get_list_sigs_output(context, fingerprint, gpg_home=gpg_home2, expected=expected) else: with pytest.raises(ScriptWorkerGPGException): sgpg.get_list_sigs_output(context, fingerprint, gpg_home=gpg_home2, expected=expected)
def test_export_key(base_context, fingerprint, private, expected): gpg = sgpg.GPG(base_context) key = sgpg.export_key(gpg, fingerprint, private=private) + "\n" with open(expected, "r") as fh: contents = fh.read() assert contents == key + "\n" or versionless(contents) == versionless( key)
def test_rebuild_gpg_home_signed(context, trusted_email, tmpdir): gpg = sgpg.GPG(context) for path in glob.glob( os.path.join(GPG_HOME, "keys", "{}.*".format(trusted_email))): shutil.copyfile(path, os.path.join(tmpdir, os.path.basename(path))) sgpg.rebuild_gpg_home_signed( context, context.config['gpg_home'], "{}{}".format(KEYS_AND_FINGERPRINTS[0][2], ".pub"), "{}{}".format(KEYS_AND_FINGERPRINTS[0][2], ".sec"), tmpdir, ) with open(os.path.join(PUBKEY_DIR, "manifest.json")) as fh: manifest = json.load(fh) for fingerprint, info in manifest.items(): with open(os.path.join(PUBKEY_DIR, info['signed_path'])) as fh: sgpg.import_key(gpg, fh.read()) if info['signing_email'] == trusted_email: sgpg.get_list_sigs_output( context, fingerprint, expected={'sig_keyids': [info['signing_keyid']]}) messages = check_sigs(context, manifest, PUBKEY_DIR, trusted_emails=[trusted_email]) assert messages == []
def test_ownertrust(context, trusted_names): """This is a fairly complex test. Create a new gnupg_home, update ownertrust with just my fingerprint. The original update will run its own verify; we then make sure to get full code coverage by testing that extra and missing fingerprints raise a ScriptWorkerGPGException. """ gpg = sgpg.GPG(context) my_fingerprint = sgpg.generate_key(gpg, "one", "one", "one") sgpg.create_gpg_conf(context.config['gpg_home'], my_fingerprint=my_fingerprint) trusted_fingerprints = [] for name in trusted_names: trusted_fingerprints.append(sgpg.generate_key(gpg, name, name, name)) # append my fingerprint to get more coverage if trusted_fingerprints: trusted_fingerprints.append(my_fingerprint) unsigned_fingerprint = sgpg.generate_key(gpg, "four", "four", "four") sgpg.update_ownertrust(context, my_fingerprint, trusted_fingerprints=trusted_fingerprints) with pytest.raises(ScriptWorkerGPGException): sgpg.verify_ownertrust(context, my_fingerprint, trusted_fingerprints + [unsigned_fingerprint]) if trusted_fingerprints: with pytest.raises(ScriptWorkerGPGException): sgpg.verify_ownertrust(context, my_fingerprint, [trusted_fingerprints[0]])
def test_generate_cot(artifacts, context): path = os.path.join(context.config['work_dir'], "foo") signed_body = cot.generate_cot(context, path=path) with open(path, "r") as fh: assert fh.read() == signed_body body = sgpg.get_body(sgpg.GPG(context), signed_body) log.info(body) assert body.rstrip() == cot.format_json(cot.generate_cot_body(context))
def test_keyid_fingerprint_exception(base_context, keyid, fingerprint, path): gpg = sgpg.GPG(base_context) assert path with pytest.raises(ScriptWorkerGPGException): sgpg.keyid_to_fingerprint(gpg, keyid.replace('C', '1').replace('F', 'C')) with pytest.raises(ScriptWorkerGPGException): sgpg.fingerprint_to_keyid( gpg, fingerprint.replace('C', '1').replace('F', 'C'))
def test_sign_key_twice(context): gpg = sgpg.GPG(context) for suffix in (".sec", ".pub"): with open("{}{}".format(KEYS_AND_FINGERPRINTS[0][2], suffix), "r") as fh: contents = fh.read() fingerprint = sgpg.import_key(gpg, contents)[0] # keys already sign themselves, so this is a second signature that should # be noop. sgpg.sign_key(context, fingerprint, signing_key=fingerprint)
def test_generate_key(context, expires, expected, tmpdir): gpg = sgpg.GPG(context) fingerprint = sgpg.generate_key(gpg, "foo", "bar", "baz", expiration=expires) for key in gpg.list_keys(): if key['fingerprint'] == fingerprint: assert key['uids'] == ['foo (bar) <baz>'] assert key['expires'] == expected assert key['trust'] == 'u' assert key['length'] == '4096'
def test_import_single_key(context, suffix, return_type): gpg = sgpg.GPG(context) with open("{}{}".format(KEYS_AND_FINGERPRINTS[0][2], suffix), "r") as fh: contents = fh.read() result = sgpg.import_key(gpg, contents, return_type=return_type) if return_type == 'result': fingerprints = [] for entry in result: fingerprints.append(entry['fingerprint']) else: fingerprints = result # the .sec fingerprints are doubled; use set() for unsorted & uniq assert set(fingerprints) == set([KEYS_AND_FINGERPRINTS[0][1]])
def check_sigs(context, manifest, pubkey_dir, trusted_emails=None): messages = [] gpg = sgpg.GPG(context) for fingerprint, info in manifest.items(): try: with open( os.path.join(pubkey_dir, "data", "{}.asc".format(fingerprint))) as fh: message = sgpg.get_body(gpg, fh.read()) if message != info['message'] + '\n': messages.append( "Unexpected message '{}', expected '{}'".format( message, info['message'])) except ScriptWorkerGPGException as exc: if trusted_emails and info['signing_email'] not in trusted_emails: pass else: messages.append("{} {} error: {}".format( fingerprint, info['signing_email'], str(exc))) return messages
def test_guess_gpg_home_GPG(base_context, gpg_home, expected): gpg = sgpg.GPG(base_context, "bar") assert sgpg.guess_gpg_home(gpg, gpg_home) == expected
def test_guess_gpg_home_GPG(base_context, gpg_home, expected, tmpdir): expected = expected or tmpdir gpg = sgpg.GPG(base_context, tmpdir) assert sgpg.guess_gpg_home(gpg, gpg_home) == expected
def test_keyid_fingerprint_conversion(base_context, keyid, fingerprint, path): gpg = sgpg.GPG(base_context) assert path assert sgpg.keyid_to_fingerprint(gpg, keyid) == fingerprint assert sgpg.fingerprint_to_keyid(gpg, fingerprint) == keyid
def test_sign_key(context): """This test calls get_list_sigs_output in several different ways. Each is valid; the main thing is more code coverage. tru:o:1:1472876459:1:3:1:5 pub:u:4096:1:EA608995918B2DF9:1472876455:::u:::escaESCA: fpr:::::::::A9F598A3179551CC664C15DEEA608995918B2DF9: uid:u::::1472876455::6477C0BAC30FB3E244C8F1907D78C6B243AFD516::two (two) <two>: sig:::1:EA608995918B2DF9:1472876455::::two (two) <two>:13x:::::8: sig:::1:9633F5F38B9BD3C5:1472876459::::one (one) <one>:10l:::::8: tru::1:1472876460:0:3:1:5 pub:u:4096:1:BC76BF8F77D1B3F5:1472876457:::u:::escaESCA: fpr:::::::::7CFAD9E699D8559F1D3A50CCBC76BF8F77D1B3F5: uid:u::::1472876457::91AC286E48FDA7378B86F63FA6DDC2A46B54808F::three (three) <three>: sig:::1:BC76BF8F77D1B3F5:1472876457::::three (three) <three>:13x:::::8: """ gpg = sgpg.GPG(context) # create my key, get fingerprint + keyid my_fingerprint = sgpg.generate_key( gpg, "one", "one", "one", key_length=GENERATE_KEY_SMALLER_KEY_SIZE) my_keyid = sgpg.fingerprint_to_keyid(gpg, my_fingerprint) # create signed key, get fingerprint + keyid signed_fingerprint = sgpg.generate_key( gpg, "two", "two", "two", key_length=GENERATE_KEY_SMALLER_KEY_SIZE) signed_keyid = sgpg.fingerprint_to_keyid(gpg, signed_fingerprint) # create unsigned key, get fingerprint + keyid unsigned_fingerprint = sgpg.generate_key( gpg, "three", "three", "three", key_length=GENERATE_KEY_SMALLER_KEY_SIZE) unsigned_keyid = sgpg.fingerprint_to_keyid(gpg, unsigned_fingerprint) # update gpg configs, sign signed key sgpg.create_gpg_conf(context.config['gpg_home'], my_fingerprint=my_fingerprint) sgpg.check_ownertrust(context) sgpg.sign_key(context, signed_fingerprint) # signed key get_list_sigs_output signed_output = sgpg.get_list_sigs_output(context, signed_fingerprint) # unsigned key get_list_sigs_output # Call get_list_sigs_output with validate=False, then parse it, for more code coverage unsigned_output1 = sgpg.get_list_sigs_output(context, unsigned_fingerprint, validate=False) unsigned_output = sgpg.parse_list_sigs_output(unsigned_output1, "unsigned") # signed key has my signature + self-signed assert sorted([signed_keyid, my_keyid]) == sorted(signed_output['sig_keyids']) assert ["one (one) <one>", "two (two) <two>"] == sorted(signed_output['sig_uids']) # unsigned key is only self-signed assert [unsigned_keyid] == unsigned_output['sig_keyids'] assert ["three (three) <three>"] == unsigned_output['sig_uids'] # sign the unsigned key and test sgpg.sign_key(context, unsigned_fingerprint, signing_key=signed_fingerprint) # Call get_list_sigs_output with expected, for more code coverage new_output = sgpg.get_list_sigs_output( context, unsigned_fingerprint, expected={ "keyid": unsigned_keyid, "fingerprint": unsigned_fingerprint, "uid": "three (three) <three>", "sig_keyids": [signed_keyid, unsigned_keyid], "sig_uids": ["three (three) <three>", "two (two) <two>"] }) # sig_uids goes unchecked; sig_keyids only checks that it's a subset. # let's do another check. assert ["three (three) <three>", "two (two) <two>"] == sorted(new_output['sig_uids'])
def test_export_unknown_key(base_context): gpg = sgpg.GPG(base_context) with pytest.raises(ScriptWorkerGPGException): sgpg.export_key(gpg, "illegal_fingerprint_lksjdflsjdkls")
def test_verify_good_signatures(base_context, params): gpg = sgpg.GPG(base_context) data = sgpg.sign(gpg, "foo", keyid=params[1]["fingerprint"]) sgpg.verify_signature(gpg, data)
def test_verify_bad_signatures(base_context, params): gpg = sgpg.GPG(base_context) data = sgpg.sign(gpg, "foo", keyid=params[1]["fingerprint"]) with pytest.raises(ScriptWorkerGPGException): sgpg.verify_signature(gpg, data)
def test_get_body(base_context, text, params, verify_sig): gpg = sgpg.GPG(base_context) data = sgpg.sign(gpg, text, keyid=params[1]["fingerprint"]) if not text.endswith('\n'): text = "{}\n".format(text) assert sgpg.get_body(gpg, data, verify_sig=verify_sig) == text