Blame lang/python/tests/t-quick-key-signing.py

Packit Service 672cf4
#!/usr/bin/env python
Packit Service 672cf4
Packit Service 672cf4
# Copyright (C) 2017 g10 Code GmbH
Packit Service 672cf4
#
Packit Service 672cf4
# This file is part of GPGME.
Packit Service 672cf4
#
Packit Service 672cf4
# GPGME is free software; you can redistribute it and/or modify it
Packit Service 672cf4
# under the terms of the GNU General Public License as published by
Packit Service 672cf4
# the Free Software Foundation; either version 2 of the License, or
Packit Service 672cf4
# (at your option) any later version.
Packit Service 672cf4
#
Packit Service 672cf4
# GPGME is distributed in the hope that it will be useful, but WITHOUT
Packit Service 672cf4
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 672cf4
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
Packit Service 672cf4
# Public License for more details.
Packit Service 672cf4
#
Packit Service 672cf4
# You should have received a copy of the GNU Lesser General Public
Packit Service 6c01f9
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit Service 672cf4
Packit Service 672cf4
from __future__ import absolute_import, print_function, unicode_literals
Packit Service 6c01f9
del absolute_import, print_function, unicode_literals
Packit Service 672cf4
Packit Service 672cf4
import gpg
Packit Service 672cf4
import itertools
Packit Service 672cf4
import time
Packit Service 672cf4
Packit Service 672cf4
import support
Packit Service 672cf4
support.assert_gpg_version((2, 1, 1))
Packit Service 672cf4
Packit Service 672cf4
with support.EphemeralContext() as ctx:
Packit Service 672cf4
    uid_counter = 0
Packit Service 672cf4
    def make_uid():
Packit Service 672cf4
        global uid_counter
Packit Service 672cf4
        uid_counter += 1
Packit Service 672cf4
        return "user{0}@invalid.example.org".format(uid_counter)
Packit Service 672cf4
Packit Service 672cf4
    def make_key():
Packit Service 672cf4
        uids = [make_uid() for i in range(3)]
Packit Service 672cf4
        res = ctx.create_key(uids[0], certify=True)
Packit Service 672cf4
        key = ctx.get_key(res.fpr)
Packit Service 672cf4
        for u in uids[1:]:
Packit Service 672cf4
            ctx.key_add_uid(key, u)
Packit Service 672cf4
        return key, uids
Packit Service 672cf4
Packit Service 672cf4
    def check_sigs(key, expected_sigs):
Packit Service 6c01f9
        keys = list(ctx.keylist(key.fpr, mode=(gpg.constants.keylist.mode.LOCAL
Packit Service 6c01f9
                                               |gpg.constants.keylist.mode.SIGS)))
Packit Service 672cf4
        assert len(keys) == 1
Packit Service 6c01f9
        key_uids = {uid.uid: [s for s in uid.signatures] for uid in keys[0].uids}
Packit Service 672cf4
        expected = list(expected_sigs)
Packit Service 672cf4
Packit Service 672cf4
        while key_uids and expected:
Packit Service 672cf4
            uid, signing_key, func = expected[0]
Packit Service 672cf4
            match = False
Packit Service 672cf4
            for i, s in enumerate(key_uids[uid]):
Packit Service 672cf4
                if signing_key.fpr.endswith(s.keyid):
Packit Service 672cf4
                    if func:
Packit Service 672cf4
                        func(s)
Packit Service 672cf4
                    match = True
Packit Service 672cf4
                    break
Packit Service 672cf4
            if match:
Packit Service 672cf4
                expected.pop(0)
Packit Service 672cf4
                key_uids[uid].pop(i)
Packit Service 672cf4
                if not key_uids[uid]:
Packit Service 672cf4
                    del key_uids[uid]
Packit Service 672cf4
Packit Service 672cf4
        assert not key_uids, "Superfluous signatures: {0}".format(key_uids)
Packit Service 672cf4
        assert not expected, "Missing signatures: {0}".format(expected)
Packit Service 672cf4
Packit Service 672cf4
    # Simplest case.  Sign without any options.
Packit Service 672cf4
    key_a, uids_a = make_key()
Packit Service 672cf4
    key_b, uids_b = make_key()
Packit Service 672cf4
    ctx.signers = [key_a]
Packit Service 672cf4
Packit Service 672cf4
    def exportable_non_expiring(s):
Packit Service 672cf4
        assert s.exportable
Packit Service 672cf4
        assert s.expires == 0
Packit Service 672cf4
Packit Service 6c01f9
    check_sigs(key_b, itertools.product(uids_b, [key_b], [exportable_non_expiring]))
Packit Service 672cf4
    ctx.key_sign(key_b)
Packit Service 6c01f9
    check_sigs(key_b, itertools.product(uids_b, [key_b, key_a], [exportable_non_expiring]))
Packit Service 672cf4
Packit Service 672cf4
    # Create a non-exportable signature, and explicitly name all uids.
Packit Service 672cf4
    key_c, uids_c = make_key()
Packit Service 672cf4
    ctx.signers = [key_a, key_b]
Packit Service 672cf4
Packit Service 672cf4
    def non_exportable_non_expiring(s):
Packit Service 672cf4
        assert s.exportable == 0
Packit Service 672cf4
        assert s.expires == 0
Packit Service 672cf4
Packit Service 672cf4
    ctx.key_sign(key_c, local=True, uids=uids_c)
Packit Service 6c01f9
    check_sigs(key_c,
Packit Service 6c01f9
               list(itertools.product(uids_c, [key_c],
Packit Service 6c01f9
                                      [exportable_non_expiring]))
Packit Service 6c01f9
               + list(itertools.product(uids_c, [key_b, key_a],
Packit Service 6c01f9
                                        [non_exportable_non_expiring])))
Packit Service 672cf4
Packit Service 672cf4
    # Create a non-exportable, expiring signature for a single uid.
Packit Service 672cf4
    key_d, uids_d = make_key()
Packit Service 672cf4
    ctx.signers = [key_c]
Packit Service 672cf4
    expires_in = 600
Packit Service 672cf4
    slack = 10
Packit Service 672cf4
Packit Service 672cf4
    def non_exportable_expiring(s):
Packit Service 672cf4
        assert s.exportable == 0
Packit Service 672cf4
        assert abs(time.time() + expires_in - s.expires) < slack
Packit Service 672cf4
Packit Service 672cf4
    ctx.key_sign(key_d, local=True, expires_in=expires_in, uids=uids_d[0])
Packit Service 6c01f9
    check_sigs(key_d,
Packit Service 6c01f9
               list(itertools.product(uids_d, [key_d],
Packit Service 6c01f9
                                      [exportable_non_expiring]))
Packit Service 6c01f9
               + list(itertools.product(uids_d[:1], [key_c],
Packit Service 6c01f9
                                        [non_exportable_expiring])))
Packit Service 672cf4
Packit Service 672cf4
    # Now sign the second in the same fashion, but use a singleton list.
Packit Service 672cf4
    ctx.key_sign(key_d, local=True, expires_in=expires_in, uids=uids_d[1:2])
Packit Service 6c01f9
    check_sigs(key_d,
Packit Service 6c01f9
               list(itertools.product(uids_d, [key_d],
Packit Service 6c01f9
                                      [exportable_non_expiring]))
Packit Service 6c01f9
               + list(itertools.product(uids_d[:2], [key_c],
Packit Service 6c01f9
                                        [non_exportable_expiring])))