Exemplo n.º 1
0
    def __init__(self, primary_keyring_fname, trustdb_fname, *args, **kwargs):
        # I don't think Keyring is inheriting from object,
        # so we can't use super()
        Keyring.__init__(self, *args, **kwargs)

        self.context.set_option('primary-keyring', primary_keyring_fname)
        self.context.set_option('trustdb-name', trustdb_fname)
        self.context.set_option('no-default-keyring')
Exemplo n.º 2
0
    def __init__(self, primary_keyring_fname, trustdb_fname, *args, **kwargs):
        # I don't think Keyring is inheriting from object,
        # so we can't use super()
        Keyring.__init__(self)   #  *args, **kwargs)

        self.context.set_option('primary-keyring', primary_keyring_fname)
        self.context.set_option('trustdb-name', trustdb_fname)
        self.context.set_option('no-default-keyring')
Exemplo n.º 3
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
Exemplo n.º 4
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
Exemplo 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
Exemplo 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)
Exemplo n.º 8
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:
            TempSplitKeyring.__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))
Exemplo n.º 9
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)
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)
Exemplo n.º 11
0
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)
Exemplo n.º 12
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)
Exemplo n.º 13
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
Exemplo n.º 14
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)
Exemplo n.º 15
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.
    fpr = keys.items()[0][0]
    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()
Exemplo n.º 16
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
Exemplo n.º 17
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()
Exemplo n.º 18
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
Exemplo n.º 19
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
Exemplo n.º 20
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
Exemplo n.º 21
0
class KeySignSection(Gtk.VBox):
    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

    def on_key_selection_changed(self, pane, keyid):
        '''This callback is attached to the signal which is emitted
        when the user changes their selection in the list of keys
        '''
        pass

    def on_key_selected(self, pane, keyid):
        '''This is the callback for when the user has committed
        to a key, i.e. the user has made a selection and wants to
        advance the program.
        '''
        log.debug('User selected key %s', keyid)

        key = list(self.keyring.get_keys(keyid).values())[0]

        keyid = key.keyid()
        fpr = key.fpr
        self.keyring.export_data(fpr, secret=False)
        keydata = self.keyring.context.stdout

        self.log.debug("Keyserver switched on! Serving key with fpr: %s", fpr)
        self.setup_server(keydata, fpr)

        self.switch_to_key_present_page(key)

    def switch_to_key_present_page(self, key):
        '''This switches the notebook to the page which
        presents the information that is needed to securely
        transfer the keydata, i.e. the fingerprint and its barcode.
        '''
        self.keyPresentPage.display_fingerprint_qr_page(key)
        self.notebook.next_page()
        # This is more of a crude hack. Once the next page is presented,
        # the back button has the focus. This is not desirable because
        # you will go back when accidentally pressing space or enter.
        self.keyPresentPage.fingerprintLabel.grab_focus()
        # FIXME: we better use set_current_page, but that requires
        # knowing which page our desired widget is on.
        # FWIW: A headerbar has named pages.

    def on_next_button_clicked(self, button):
        '''A helper for legacy reasons to enable a next button
        
        All it does is retrieve the selection from the TreeView and
        call the signal handler for when the user committed to a key
        '''
        name, email, keyid = self.keysPage.get_items_from_selection()
        return self.on_key_selected(button, keyid)

    def on_button_clicked(self, button):

        page_index = self.notebook.get_current_page()

        if button == self.backButton:

            if page_index == 1:
                self.log.debug("Keyserver switched off")
                self.stop_server()

            self.notebook.prev_page()

    def setup_server(self, keydata, fingerprint):
        """
        Starts the key-server which serves the provided keydata and
        announces the fingerprint as TXT record using Avahi
        """
        self.log.info('Serving now')
        self.log.debug('About to call %r', Keyserver.ServeKeyThread)
        self.keyserver = Keyserver.ServeKeyThread(str(keydata), fingerprint)
        self.log.info('Starting thread %r', self.keyserver)
        self.keyserver.start()
        self.log.info('Finsihed serving')
        return False

    def stop_server(self):
        self.keyserver.shutdown()
Exemplo n.º 22
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]))
Exemplo n.º 23
0
class KeysPage(Gtk.VBox):
    '''This represents a list of keys with the option for the user
    to select one key to proceed.
    
    This class emits a `key-selection-changed' signal when the user
    initially selects a key such that it is highlighted.
    
    The `key-selected' signal is emitted when the user commits
    to a key, i.e. by pressing a designated button to make his
    selection public.
    '''
    __gsignals__ = {
        str('key-selected'): (
            GObject.SIGNAL_RUN_LAST,
            None,
            # Hm, this is a str for now, but ideally
            # it'd be the full key object
            (
                str, )),
        str('key-selection-changed'): (
            GObject.SIGNAL_RUN_LAST,
            None,
            # Hm, this is a str for now, but ideally
            # it'd be the full key object
            (
                str, )),
    }

    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)

    # We could make it a @staticmethod, but the returned items
    # are bound to the model, anyway.  So it probably doesn't
    # make much sense to have a static function, anyway.
    def get_items_from_selection(self, selection=None):
        '''Returns the elements in the ListStore for the given selection'''
        s = selection or self.treeView.get_selection()
        model, paths = s.get_selected_rows()
        name = email = keyid = None
        for path in paths:
            iterator = model.get_iter(path)
            (name, email, keyid) = model.get(iterator, 0, 1, 2)
            break

        return (name, email, keyid)

    def on_selection_changed(self, selection, *args):
        log.debug('Selected new TreeView item %s = %s', selection, args)

        name, email, keyid = self.get_items_from_selection(selection)

        key = self.keysDict[keyid]
        self.emit('key-selection-changed', keyid)

        try:
            exp_date = datetime.fromtimestamp(float(key.expiry))
        except TypeError as e:
            # This might be the case when the key.expiry is already a timedate
            exp_date = key.expiry
        except ValueError as e:
            # This happens when converting an empty string to a datetime.
            exp_date = None

        if exp_date is None:
            expiry = "No expiration date"
        else:
            expiry = "{:%Y-%m-%d %H:%M:%S}".format(exp_date)

        pane = self.right_pane
        for child in pane.get_children():
            # Ouch, this is not very efficient.
            # But this deals with the fact that the first
            # label in the pane is a "Select a key on the left"
            # text.
            pane.remove(child)
        ctx = {'keyid': keyid, 'expiry': expiry, 'sigs': ''}
        keyid_label = Gtk.Label(label='Key {keyid}'.format(**ctx))
        expiration_label = Gtk.Label(label='Expires: {expiry}'.format(**ctx))
        #signatures_label = Gtk.Label(label='{sigs} signatures'.format(**ctx))
        publish_button = Gtk.Button(label='Go ahead!'.format(**ctx))
        publish_button.connect('clicked', self.on_publish_button_clicked, key)
        for w in (
                keyid_label,
                expiration_label
                #, signatures_label
                ,
                publish_button):
            pane.add(w)
        pane.show_all()

    def on_row_activated(self, treeview, tree_path, column):
        '''A callback for when the user "activated" a row,
        e.g. by double-clicking an entry.
        
        It emits the key-selected signal.
        '''
        # We just hijack the existing function.
        # I'm sure we could get the required information out of
        # the tree_path and column, but I don't know how.
        name, email, keyid = self.get_items_from_selection()
        self.emit('key-selected', keyid)

    def on_publish_button_clicked(self, button, key, *args):
        '''Callback for when the user has expressed their wish
        to publish a key on the network.  It will emit a "key-selected"
        signal with the ID of the selected key.'''
        log.debug('Clicked publish for key (%s) %s (%s)', type(key), key, args)
        keyid = key.keyid()
        self.emit('key-selected', keyid)
Exemplo n.º 24
0
    def __init__(self, keySection):
        super(KeysPage, self).__init__()

        # pass a reference to KeySignSection in order to access its widgets
        self.keySection = keySection

        # set up the list store to be filled up with user's gpg keys
        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
        for key in self.keyring.get_keys(None, True, False).values():
            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))

        # 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)

        # 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)
Exemplo n.º 25
0
class KeysPage(Gtk.VBox):
    '''This represents a list of keys with the option for the user
    to select one key to proceed.
    
    This class emits a `key-selection-changed' signal when the user
    initially selects a key such that it is highlighted.
    
    The `key-selected' signal is emitted when the user commits
    to a key, i.e. by pressing a designated button to make his
    selection public.
    '''
    __gsignals__ = {
        str('key-selected'): (GObject.SIGNAL_RUN_LAST, None,
                         # Hm, this is a str for now, but ideally
                         # it'd be the full key object
                         (str,)),
        str('key-selection-changed'): (GObject.SIGNAL_RUN_LAST, None,
                         # Hm, this is a str for now, but ideally
                         # it'd be the full key object
                         (str,)),
    }

    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)


    # We could make it a @staticmethod, but the returned items
    # are bound to the model, anyway.  So it probably doesn't
    # make much sense to have a static function, anyway.
    def get_items_from_selection(self, selection=None):
        '''Returns the elements in the ListStore for the given selection'''
        s = selection or self.treeView.get_selection()
        model, paths = s.get_selected_rows()
        name = email = keyid = None
        for path in paths:
            iterator = model.get_iter(path)
            (name, email, keyid) = model.get(iterator, 0, 1, 2)
            break

        return (name, email, keyid)


    def on_selection_changed(self, selection, *args):
        log.debug('Selected new TreeView item %s = %s', selection, args)
        
        name, email, keyid = self.get_items_from_selection(selection)
        
        key = self.keysDict[keyid]
        self.emit('key-selection-changed', keyid)
        
        try:
            exp_date = datetime.fromtimestamp(float(key.expiry))
        except TypeError as e:
            # This might be the case when the key.expiry is already a timedate
            exp_date = key.expiry
        except ValueError as e:
            # This happens when converting an empty string to a datetime.
            exp_date = None

        if exp_date is None:
            expiry = "No expiration date"
        else:
            expiry = "{:%Y-%m-%d %H:%M:%S}".format(exp_date)

        pane = self.right_pane
        for child in pane.get_children():
            # Ouch, this is not very efficient.
            # But this deals with the fact that the first
            # label in the pane is a "Select a key on the left"
            # text.
            pane.remove(child)
        ctx = {'keyid':keyid, 'expiry':expiry, 'sigs':''}
        keyid_label = Gtk.Label(label='Key {keyid}'.format(**ctx))
        expiration_label = Gtk.Label(label='Expires: {expiry}'.format(**ctx))
        #signatures_label = Gtk.Label(label='{sigs} signatures'.format(**ctx))
        publish_button = Gtk.Button(label='Go ahead!'.format(**ctx))
        publish_button.connect('clicked', self.on_publish_button_clicked, key)
        for w in (keyid_label
                  , expiration_label
                  #, signatures_label
                  , publish_button
                  ):
            pane.add(w)
        pane.show_all()


    def on_row_activated(self, treeview, tree_path, column):
        '''A callback for when the user "activated" a row,
        e.g. by double-clicking an entry.
        
        It emits the key-selected signal.
        '''
        # We just hijack the existing function.
        # I'm sure we could get the required information out of
        # the tree_path and column, but I don't know how.
        name, email, keyid = self.get_items_from_selection()
        self.emit('key-selected', keyid)


    def on_publish_button_clicked(self, button, key, *args):
        '''Callback for when the user has expressed their wish
        to publish a key on the network.  It will emit a "key-selected"
        signal with the ID of the selected key.'''
        log.debug('Clicked publish for key (%s) %s (%s)', type(key), key, args)
        keyid = key.keyid()
        self.emit('key-selected', keyid)
Exemplo n.º 26
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
Exemplo n.º 27
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)
Exemplo n.º 28
0
def get_public_key_data(fpr):
    keydata = Keyring().export_data(fpr)
    return keydata
Exemplo n.º 29
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)
Exemplo n.º 30
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)