Esempio n. 1
0
    def __init__(self):
        super(KeyDetailsPage, self).__init__()
        self.set_spacing(10)
        self.log = logging.getLogger()

        # FIXME: this should be moved to KeySignSection
        self.keyring = Keyring()

        uidsLabel = Gtk.Label()
        uidsLabel.set_text("UIDs")

        # this will later be populated with uids when user selects a key
        self.uidsBox = Gtk.VBox(spacing=5)

        self.expireLabel = Gtk.Label()
        self.expireLabel.set_text("Expires 0000-00-00")

        self.signatures_label = signaturesLabel = Gtk.Label()
        signaturesLabel.set_text("Signatures")

        # this will also be populated later
        self.signaturesBox = Gtk.VBox(spacing=5)

        self.pack_start(uidsLabel, False, False, 0)
        self.pack_start(self.uidsBox, True, True, 0)
        self.pack_start(self.expireLabel, False, False, 0)
        self.pack_start(signaturesLabel, False, False, 0)
        self.pack_start(self.signaturesBox, True, True, 0)
Esempio n. 2
0
def get_usable_secret_keys(pattern="", homedir=None):
    '''Returns all secret keys which can be used to sign a key'''
    keyring = Keyring(homedir=homedir)
    return get_usable_keys_from_keyring(keyring=keyring,
                                        pattern=pattern,
                                        public=False,
                                        secret=True)
Esempio n. 3
0
def get_usable_keys(pattern="", homedir=None):
    '''Uses get_keys on the keyring and filters for
    non revoked, expired, disabled, or invalid keys'''
    log.debug('Retrieving keys for %s, %s', pattern, homedir)
    keyring = Keyring(homedir=homedir)
    return get_usable_keys_from_keyring(keyring=keyring,
                                        pattern=pattern,
                                        public=True,
                                        secret=False)
Esempio n. 4
0
def get_public_key_data(fpr, keyring=None):
    """Returns keydata for a given fingerprint

    In fact, fpr could be anything that gpg happily exports.
    """
    if not keyring:
        keyring = Keyring()
    keydata = keyring.export_data(fpr)
    return keydata
Esempio n. 5
0
def get_public_key_data(fpr, homedir=None):
    """Returns keydata for a given fingerprint
    
    In fact, fpr could be anything that gpg happily exports.
    """
    keyring = Keyring(homedir=homedir)
    keydata = keyring.export_data(fpr)
    if not keydata:
        s = "No data to export for {} (in {})".format(fpr, homedir)
        raise ValueError(s)
    return keydata
Esempio n. 6
0
    def __init__(self, base_keyring=None, *args, **kwargs):
        # Not a new style class...
        if issubclass(self.__class__, object):
            super(TempSigningKeyring, self).__init__(*args, **kwargs)
        else:
            TempKeyring.__init__(self, *args, **kwargs)

        if base_keyring is None:
            base_keyring = Keyring()
        # Copy the public parts of the secret keys to the tmpkeyring
        for fpr, key in base_keyring.get_keys(None, secret=True,
                                              public=False).items():
            self.import_data(base_keyring.export_data(fpr))
def main():
    k = Keyring()
    secret_keys = k.get_keys(public=False, secret=True)
    log.debug('Secret Keys: %s', secret_keys)
    
    for fpr, key in secret_keys.items():
        # Because gnupg does not list whether the key has been revoked
        # when listing secret keys, we need to list public keys
        pub_keys = k.get_keys(fpr, public=True)
        assert len(pub_keys) == 1
        pub_key = pub_keys[fpr]
        
        revoked = pub_key.revoked
        log.debug("Key %s is revoked: %r", pub_key, revoked)
def main():
    k = Keyring()
    secret_keys = k.get_keys(public=False, secret=True)
    log.debug('Secret Keys: %s', secret_keys)

    for fpr, key in secret_keys.items():
        log.debug("Keys: %s", key)
        exp = key.expiry
        log.debug("Key's expiry: %r", exp)
        if exp:
            expiry = datetime.fromtimestamp(int(exp))
            now = datetime.now()
            expired = now > expiry
        else:
            expired = False
        log.debug("Key's expired: %s - %s", key.expired, expired)
Esempio n. 9
0
    def __init__(self):
        '''Initialises the section which lets the user
        choose a key to be signed by other person.
        '''
        super(KeySignSection, self).__init__()

        self.log = logging.getLogger(__name__)
        self.keyring = Keyring()

        # these are needed later when we need to get details about
        # a selected key
        self.keysPage = KeysPage()
        self.keysPage.connect('key-selection-changed',
                              self.on_key_selection_changed)
        self.keysPage.connect('key-selected', self.on_key_selected)
        self.keyDetailsPage = KeyDetailsPage()
        self.keyPresentPage = KeyPresentPage()

        # create back button
        self.backButton = Gtk.Button('Back')
        self.backButton.set_image(
            Gtk.Image.new_from_icon_name("go-previous", Gtk.IconSize.BUTTON))
        self.backButton.set_always_show_image(True)
        self.backButton.connect('clicked', self.on_button_clicked)

        # set up notebook container
        self.notebook = Gtk.Notebook()
        self.notebook.append_page(self.keysPage, None)
        vbox = Gtk.VBox()
        # We place the button at the top, but that might not be the
        # smartest thing to do. Feel free to rearrange
        # FIXME: Consider a GtkHeaderBar for the application
        vbox.pack_start(self.backButton, False, False, 0)
        vbox.pack_start(self.keyPresentPage, True, True, 10)
        self.notebook.append_page(vbox, None)
        self.notebook.set_show_tabs(False)

        self.pack_start(self.notebook, True, True, 0)

        # this will hold a reference to the last key selected
        self.last_selected_key = None

        # When obtaining a key is successful,
        # it will save the key data in this field
        self.received_key_data = None

        self.keyserver = None
Esempio n. 10
0
def signatures_for_keyid(keyid, keyring=None):
    '''Returns the list of signatures for a given key id
    
    This will call out to GnuPG list-sigs, using Monkeysign,
    and parse the resulting string into a list of signatures.
    
    A default Keyring will be used unless you pass an instance
    as keyring argument.
    '''
    if keyring is None:
        kr = Keyring()
    else:
        kr = keyring

    # FIXME: this would be better if it was done in monkeysign
    kr.context.call_command(['list-sigs', keyid])
    siglist = parse_sig_list(kr.context.stdout)

    return siglist
Esempio n. 11
0
def get_usable_secret_keys(keyring=None, pattern=None):
    '''Returns all secret keys which can be used to sign a key

    Uses get_keys on the keyring and filters for
    non revoked, expired, disabled, or invalid keys'''
    if keyring is None:
        keyring = Keyring()
    secret_keys_dict = keyring.get_keys(pattern=pattern,
                                        public=False,
                                        secret=True)
    secret_key_fprs = secret_keys_dict.keys()
    log.debug('Detected secret keys: %s', secret_key_fprs)
    usable_keys_fprs = filter(
        lambda fpr: get_usable_keys(keyring, pattern=fpr, public=True),
        secret_key_fprs)
    usable_keys = [
        Key.from_monkeysign(secret_keys_dict[fpr]) for fpr in usable_keys_fprs
    ]

    log.info('Returning usable private keys: %s', usable_keys)
    return usable_keys
Esempio n. 12
0
def main():
    import sys
    key = sys.argv[1]
    keyring = Keyring()
    keys = keyring.get_keys(key)
    # Heh, we take the first key here. Maybe we should raise a warning
    # or so, when there is more than one key.
    key = next(iter(keys.items()))[1]
    fpr = key.fpr
    data = 'OPENPGP4FPR:' + fpr

    w = Gtk.Window()
    w.connect("delete-event", Gtk.main_quit)
    w.set_default_size(100, 100)
    v = Gtk.VBox()
    label = Gtk.Label(data)
    qr = QRImage(data)
    v.add(label)
    v.add(qr)
    w.add(v)
    w.show_all()
    Gtk.main()
Esempio n. 13
0
def get_usable_keys(keyring=None, *args, **kwargs):
    '''Uses get_keys on the keyring and filters for
    non revoked, expired, disabled, or invalid keys'''
    log.debug('Retrieving keys for %s, %s', args, kwargs)
    if keyring is None:
        keyring = Keyring()
    keys_dict = keyring.get_keys(*args, **kwargs)
    assert keys_dict is not None, keyring.context.stderr

    def is_usable(key):
        unusable =    key.invalid or key.disabled \
                   or key.expired or key.revoked
        log.debug('Key %s is invalid: %s (i:%s, d:%s, e:%s, r:%s)', key,
                  unusable, key.invalid, key.disabled, key.expired,
                  key.revoked)
        return not unusable

    # keys_fpr = keys_dict.items()
    keys = keys_dict.values()
    usable_keys = [Key.from_monkeysign(key) for key in keys if is_usable(key)]

    log.debug('Identified usable keys: %s', usable_keys)
    return usable_keys
Esempio n. 14
0
    def test_sign_and_encrypt(self):
        # Let's imagine we've just got sent the key from the key-sending side
        keydata = open(self.sender_key, "rb").read()
        # for some reason pgpy does not like the stray data before
        # https://github.com/SecurityInnovation/PGPy/issues/218
        keydata = keydata[keydata.index('-----'):]

        # We find out what UIDs the sender key has
        keys = get_usable_keys(homedir=self.sender_homedir)
        assert_equals(1, len(keys))
        key = keys[0]
        uids = key.uidslist
        del key
        del keys

        # We are the receiver and we sign the sender's key.
        # This is a tuple (uid, encrypted)
        uid_encrypted = list(
            sign_keydata_and_encrypt(keydata,
                                     error_cb=None,
                                     homedir=self.receiver_homedir))
        assert_equals(len(uids), len(uid_encrypted))
        signatures_before = {}
        signatures_after = {}
        import pgpy
        pgpykeys = pgpy.PGPKey.from_blob(keydata)
        log.info("Loaded Keys: %r", pgpykeys)
        k = pgpykeys[0]
        for uid in k.userids:
            # We make the UID a string, because we might not get the
            # very same object back later. And I don't know whether
            # the dict uses "is" or "eq" for finding members
            signatures_before[u"{}".format(uid)] = uid._signatures

        for plain_uid, enc_uid in zip(uids, uid_encrypted):
            uid_from_signing = enc_uid[0]
            signed_uid = enc_uid[1]
            # The test doesn't work so well, because comments
            # are not rendered :-/
            # assert_in(uid.uid, [e[0] for e in uid_encrypted])

            # Decrypt...
            from monkeysign.gpg import Keyring
            # We sent back the key to the key-sending side
            kr = Keyring(homedir=self.sender_homedir)
            log.info("encrypted UID: %r", enc_uid)
            decrypted = kr.decrypt_data(signed_uid)
            log.info("ctx out: %r", kr.context.stdout)
            log.info("ctx err: %r", kr.context.stderr)
            assert_true(decrypted, "Error decrypting %r" % signed_uid)

            # Now we have the signed UID. We want see if it really carries a signature.
            pgpykeys = pgpy.PGPKey.from_blob(decrypted)
            log.info("Loaded Signed Keys: %r", pgpykeys)
            k = pgpykeys[0]
            # assert_equal(uid_from_signing, k.userids[0])
            assert_equal(len(k.userids), 1)
            uid = k.userids[0]
            uidstr = u"{}".format(uid)
            assert_in(uidstr, signatures_before)
            # Now we have the signed UID. We want see if it really carries a signature.
            signatures_after[uidstr] = uid._signatures
            assert_less(len(signatures_before[uidstr]),
                        len(signatures_after[uidstr]))
Esempio n. 15
0
    def sign_key_async(self, fingerprint=None, callback=None, data=None, error_cb=None):
        self.log.debug("I will sign key with fpr {}".format(fingerprint))

        keyring = Keyring()
        keyring.context.set_option('export-options', 'export-minimal')

        tmpkeyring = TempSigningKeyring(keyring)
        # Eventually, we want to let the user select their keys to sign with
        # For now, we just take whatever is there.
        secret_keys = get_usable_secret_keys(tmpkeyring)
        self.log.info('Signing with these keys: %s', secret_keys)

        keydata = data or self.received_key_data
        if keydata:
            stripped_key = MinimalExport(keydata)
            fpr = fingerprint_for_key(stripped_key)
            if fingerprint is None:
                # The user hasn't provided any data to operate on
                fingerprint = fpr

            if not fingerprint == fpr:
                self.log.warning('Something strange is going on. '
                    'We wanted to sign fingerprint "%s", received '
                    'keydata to operate on, but the key has fpr "%s".',
                    fingerprint, fpr)
                
        else: # Do we need this branch at all?
            if fingerprint is None:
                raise ValueError('You need to provide either keydata or a fpr')
            self.log.debug("looking for key %s in your keyring", fingerprint)
            keyring.context.set_option('export-options', 'export-minimal')
            stripped_key = keyring.export_data(fingerprint)

        self.log.debug('Trying to import key\n%s', stripped_key)
        if tmpkeyring.import_data(stripped_key):
            # 3. for every user id (or all, if -a is specified)
            # 3.1. sign the uid, using gpg-agent
            keys = tmpkeyring.get_keys(fingerprint)
            self.log.info("Found keys %s for fp %s", keys, fingerprint)
            assert len(keys) == 1, "We received multiple keys for fp %s: %s" % (fingerprint, keys)
            key = keys[fingerprint]
            uidlist = key.uidslist
            
            for secret_key in secret_keys:
                secret_fpr = secret_key.fpr
                self.log.info('Setting up to sign with %s', secret_fpr)
                # We need to --always-trust, because GnuPG would print
                # warning about the trustdb.  I think this is because
                # we have a newly signed key whose trust GnuPG wants to
                # incorporate into the trust decision.
                tmpkeyring.context.set_option('always-trust')
                tmpkeyring.context.set_option('local-user', secret_fpr)
                # FIXME: For now, we sign all UIDs. This is bad.
                ret = tmpkeyring.sign_key(uidlist[0].uid, signall=True)
                self.log.info("Result of signing %s on key %s: %s", uidlist[0].uid, fingerprint, ret)


            for uid in uidlist:
                uid_str = uid.uid
                self.log.info("Processing uid %s %s", uid, uid_str)

                # 3.2. export and encrypt the signature
                # 3.3. mail the key to the user
                signed_key = UIDExport(uid_str, tmpkeyring.export_data(uid_str))
                self.log.info("Exported %d bytes of signed key", len(signed_key))
                # self.signui.tmpkeyring.context.set_option('armor')
                tmpkeyring.context.set_option('always-trust')
                encrypted_key = tmpkeyring.encrypt_data(data=signed_key, recipient=uid_str)

                keyid = str(key.keyid())
                ctx = {
                    'uid' : uid_str,
                    'fingerprint': fingerprint,
                    'keyid': keyid,
                }
                # We could try to dir=tmpkeyring.dir
                # We do not use the with ... as construct as the
                # tempfile might be deleted before the MUA had the chance
                # to get hold of it.
                # Hence we reference the tmpfile and hope that it will be properly
                # cleaned up when this object will be destroyed...
                tmpfile = NamedTemporaryFile(prefix='gnome-keysign-', suffix='.asc')
                self.tmpfiles.append(tmpfile)
                filename = tmpfile.name
                self.log.info('Writing keydata to %s', filename)
                tmpfile.write(encrypted_key)
                # Interesting, sometimes it would not write the whole thing out,
                # so we better flush here
                tmpfile.flush()
                # As we're done with the file, we close it.
                #tmpfile.close()

                subject = Template(SUBJECT).safe_substitute(ctx)
                body = Template(BODY).safe_substitute(ctx)
                self.email_file (to=uid_str, subject=subject,
                                 body=body, files=[filename])


            # FIXME: Can we get rid of self.tmpfiles here already? Even if the MUA is still running?


            # 3.4. optionnally (-l), create a local signature and import in
            # local keyring
            # 4. trash the temporary keyring


        else:
            self.log.error('data found in barcode does not match a OpenPGP fingerprint pattern: %s', fingerprint)
            if error_cb:
                GLib.idle_add(error_cb, data)

        return False
Esempio n. 16
0
    def __init__(self, show_public_keys=False):
        '''Sets the widget up.
        
        The show_public_keys parameter is meant for development
        purposes only.  If set to True, the widget will show
        the public keys, too.  Otherwise, secret keys are shown.
        '''
        super(KeysPage, self).__init__()

        # set up the list store to be filled up with user's gpg keys
        # Note that other functions expect a certain structure to
        # this ListStore, e.g. when parsing the selection of the
        # TreeView, i.e. in get_items_from_selection.
        self.store = Gtk.ListStore(str, str, str)

        # FIXME: this should be moved to KeySignSection
        self.keyring = Keyring()  # the user's keyring

        self.keysDict = {}

        # FIXME: this should be a callback function to update the display
        # when a key is changed/deleted
        keys = self.keyring.get_keys(None,
                                     secret=True,
                                     public=show_public_keys)
        for fpr, key in keys.items():
            if key.invalid or key.disabled or key.expired or key.revoked:
                continue

            uidslist = key.uidslist  #UIDs: Real Name (Comment) <email@address>
            keyid = str(key.keyid())  # the key's short id

            if not keyid in self.keysDict:
                self.keysDict[keyid] = key

            for e in uidslist:
                uid = str(e.uid)
                # remove the comment from UID (if it exists)
                com_start = uid.find('(')
                if com_start != -1:
                    com_end = uid.find(')')
                    uid = uid[:com_start].strip() + uid[com_end + 1:].strip()

                # split into user's name and email
                tokens = uid.split('<')
                name = tokens[0].strip()
                email = 'unknown'
                if len(tokens) > 1:
                    email = tokens[1].replace('>', '').strip()

                self.store.append((name, email, keyid))

        if len(self.store) == 0:
            self.pack_start(Gtk.Label("You don't have a private key"), True,
                            True, 0)
        else:
            # create the tree view
            self.treeView = Gtk.TreeView(model=self.store)
            # setup 'Name' column
            nameRenderer = Gtk.CellRendererText()
            nameColumn = Gtk.TreeViewColumn("Name", nameRenderer, text=0)

            # setup 'Email' column
            emailRenderer = Gtk.CellRendererText()
            emailColumn = Gtk.TreeViewColumn("Email", emailRenderer, text=1)

            # setup 'Key' column
            keyRenderer = Gtk.CellRendererText()
            keyColumn = Gtk.TreeViewColumn("Key", keyRenderer, text=2)

            self.treeView.append_column(nameColumn)
            self.treeView.append_column(emailColumn)
            self.treeView.append_column(keyColumn)

            self.treeView.connect('row-activated', self.on_row_activated)

            # make the tree view resposive to single click selection
            self.treeView.get_selection().connect('changed',
                                                  self.on_selection_changed)

            # make the tree view scrollable
            self.scrolled_window = Gtk.ScrolledWindow()
            self.scrolled_window.set_policy(Gtk.PolicyType.NEVER,
                                            Gtk.PolicyType.AUTOMATIC)
            self.scrolled_window.add(self.treeView)
            self.scrolled_window.set_min_content_height(200)

            #self.pack_start(self.scrolled_window, True, True, 0)

            self.hpane = Gtk.HPaned()
            self.hpane.pack1(self.scrolled_window, False, False)
            self.right_pane = Gtk.VBox()
            right_label = Gtk.Label(label='Select key on the left')
            self.right_pane.add(right_label)
            # Hm, right now, the width of the right pane changes, when
            # a key is selected, because the right pane's content will be
            # wider when it displays expiration et al.
            # Can we hint at that fact and make the VBox a bit wider than necessary?
            #padded_label = Gtk.Label(label='Select key on the left'*3)
            #self.right_pane.add(padded_label)
            self.hpane.pack2(self.right_pane, True, False)

            self.pack_start(self.hpane, True, True, 0)
Esempio n. 17
0
def sign_keydata(keydata, error_cb=None, homedir=None):
    """Signs OpenPGP keydata with your regular GnuPG secret keys
    
    If error_cb is provided, that function is called with any exception
    occuring during signing of the key.  If error_cb is False, any
    exception is raised.
    
    yields pairs of (uid, signed_uid)
    """
    log = logging.getLogger(__name__ + ':sign_keydata_encrypt')

    tmpkeyring = TempSigningKeyring(homedir=homedir,
                                    base_keyring=Keyring(homedir=homedir))
    tmpkeyring.context.set_option('export-options', 'export-minimal')
    # Eventually, we want to let the user select their keys to sign with
    # For now, we just take whatever is there.
    secret_keys = get_usable_keys_from_keyring(keyring=tmpkeyring,
                                               pattern="",
                                               public=False,
                                               secret=True)
    log.info('Signing with these keys: %s', secret_keys)

    stripped_key = MinimalExport(keydata)
    fingerprint = fingerprint_from_keydata(stripped_key)

    log.debug('Trying to import key\n%s', stripped_key)
    if tmpkeyring.import_data(stripped_key):
        # 3. for every user id (or all, if -a is specified)
        # 3.1. sign the uid, using gpg-agent
        keys = tmpkeyring.get_keys(fingerprint)
        log.info("Found keys %s for fp %s", keys, fingerprint)
        if len(keys) != 1:
            raise ValueError("We received multiple keys for fp %s: %s" %
                             (fingerprint, keys))
        key = keys[fingerprint]
        uidlist = key.uidslist

        for secret_key in secret_keys:
            secret_fpr = secret_key.fpr
            log.info('Setting up to sign with %s', secret_fpr)
            # We need to --always-trust, because GnuPG would print
            # warning about the trustdb.  I think this is because
            # we have a newly signed key whose trust GnuPG wants to
            # incorporate into the trust decision.
            tmpkeyring.context.set_option('always-trust')
            tmpkeyring.context.set_option('local-user', secret_fpr)
            # FIXME: For now, we sign all UIDs. This is bad.
            try:
                ret = tmpkeyring.sign_key(fingerprint, signall=True)
            except GpgRuntimeError as e:
                uid = uidlist[0].uid
                log.exception(
                    "Error signing %r with secret key %r. stdout: %r, stderr: %r",
                    uid, secret_key, tmpkeyring.context.stdout,
                    tmpkeyring.context.stderr)
                if error_cb:
                    e.uid = uid
                    error_cb(e)
                else:
                    raise
                continue
            log.info("Result of signing %s on key %s: %s", uidlist[0].uid,
                     fingerprint, ret)

        for uid in uidlist:
            uid_str = uid.uid
            log.info("Processing uid %r %s", uid, uid_str)

            # 3.2. export and encrypt the signature
            # 3.3. mail the key to the user
            signed_key = UIDExport(uid_str, tmpkeyring.export_data(uid_str))
            log.info("Exported %d bytes of signed key", len(signed_key))
            yield (uid, signed_key)
Esempio n. 18
0
def get_public_key_data(fpr):
    keydata = Keyring().export_data(fpr)
    return keydata