]> git.ipfire.org Git - pakfire.git/commitdiff
libpakfire: Add capability to generate keys and export them
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 23 Nov 2017 16:30:00 +0000 (17:30 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 23 Nov 2017 16:30:00 +0000 (17:30 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/_pakfire/_pakfiremodule.c
src/_pakfire/key.c [new file with mode: 0644]
src/_pakfire/key.h [new file with mode: 0644]
src/_pakfire/pool.c
src/libpakfire/include/pakfire/key.h [new file with mode: 0644]
src/libpakfire/include/pakfire/types.h
src/libpakfire/key.c [new file with mode: 0644]
src/libpakfire/libpakfire.sym
src/pakfire/base.py
src/pakfire/cli.py

index fd83269706624ba4f493f93018a2207b4fd4ab50..e4168bc2517f107d0d4c532eb46e9e706d007ca6 100644 (file)
@@ -181,6 +181,8 @@ _pakfire_la_SOURCES = \
        src/_pakfire/capabilities.h \
        src/_pakfire/constants.h \
        src/_pakfire/errors.h \
+       src/_pakfire/key.c \
+       src/_pakfire/key.h \
        src/_pakfire/package.c \
        src/_pakfire/package.h \
        src/_pakfire/pool.c \
@@ -236,6 +238,7 @@ libpakfire_la_SOURCES = \
        src/libpakfire/errno.c \
        src/libpakfire/file.c \
        src/libpakfire/filter.c \
+       src/libpakfire/key.c \
        src/libpakfire/package.c \
        src/libpakfire/packagelist.c \
        src/libpakfire/pool.c \
@@ -260,6 +263,7 @@ pkginclude_HEADERS += \
        src/libpakfire/include/pakfire/file.h \
        src/libpakfire/include/pakfire/filter.h \
        src/libpakfire/include/pakfire/i18n.h \
+       src/libpakfire/include/pakfire/key.h \
        src/libpakfire/include/pakfire/package.h \
        src/libpakfire/include/pakfire/packagecache.h \
        src/libpakfire/include/pakfire/packagelist.h \
index 01900cf5930f4404439c190bab443f26f2f11fd8..c226407a17c4a4937274b0dc1ccef4533b77b2f0 100644 (file)
@@ -29,6 +29,7 @@
 #include "capabilities.h"
 #include "constants.h"
 #include "errors.h"
+#include "key.h"
 #include "package.h"
 #include "pool.h"
 #include "problem.h"
@@ -129,6 +130,13 @@ PyMODINIT_FUNC PyInit__pakfire(void) {
        Py_INCREF(&ArchiveType);
        PyModule_AddObject(module, "Archive", (PyObject *)&ArchiveType);
 
+       // Key
+       if (PyType_Ready(&KeyType) < 0)
+               return NULL;
+
+       Py_INCREF(&KeyType);
+       PyModule_AddObject(module, "Key", (PyObject *)&KeyType);
+
        // Package
        if (PyType_Ready(&PackageType) < 0)
                return NULL;
diff --git a/src/_pakfire/key.c b/src/_pakfire/key.c
new file mode 100644 (file)
index 0000000..67ca5a4
--- /dev/null
@@ -0,0 +1,119 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2017 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <Python.h>
+
+#include <pakfire/key.h>
+#include <pakfire/util.h>
+
+#include "key.h"
+
+static PyObject* Key_new_core(PyTypeObject* type, PoolObject* pool, PakfireKey key) {
+       KeyObject* self = (KeyObject *)type->tp_alloc(type, 0);
+       if (self) {
+               self->pool = pool;
+               self->key  = key;
+       }
+
+       return (PyObject *)self;
+}
+
+PyObject* new_key(PoolObject* pool, PakfireKey key) {
+       return Key_new_core(&KeyType, pool, key);
+}
+
+static PyObject* Key_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
+       return Key_new_core(type, NULL, NULL);
+}
+
+static void Key_dealloc(KeyObject* self) {
+       if (self->key)
+               pakfire_key_free(self->key);
+
+       Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static int Key_init(KeyObject* self, PyObject* args, PyObject* kwds) {
+       PyObject* pool;
+       const char* fingerprint = NULL;
+
+       if (!PyArg_ParseTuple(args, "O!s", &PoolType, &pool, &fingerprint))
+               return -1;
+
+       self->pool = (PoolObject *)pool;
+       Py_INCREF(self->pool);
+
+       self->key = pakfire_key_get(self->pool->pool, fingerprint);
+       if (!self->key)
+               return -1;
+
+       return 0;
+}
+
+static PyObject* Key_repr(KeyObject* self) {
+       const char* fingerprint = pakfire_key_get_fingerprint(self->key);
+
+       return PyUnicode_FromFormat("<_pakfire.Key (%s)>", fingerprint);
+}
+
+static PyObject* Key_str(KeyObject* self) {
+       return NULL;
+}
+
+static PyObject* Key_export(KeyObject* self, PyObject* args) {
+       int secret = 0;
+
+       if (!PyArg_ParseTuple(args, "|p", &secret))
+               return NULL;
+
+       pakfire_key_export_mode_t mode;
+       if (secret)
+               mode = PAKFIRE_KEY_EXPORT_MODE_SECRET;
+       else
+               mode = PAKFIRE_KEY_EXPORT_MODE_PUBLIC;
+
+       // Export the key
+       char* export = pakfire_key_export(self->key, mode);
+
+       PyObject* object = PyUnicode_FromFormat("%s", export);
+       pakfire_free(export);
+
+       return object;
+}
+
+static struct PyMethodDef Key_methods[] = {
+       {"export", (PyCFunction)Key_export, METH_VARARGS, NULL},
+       { NULL },
+};
+
+PyTypeObject KeyType = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       tp_name:            "_pakfire.Key",
+       tp_basicsize:       sizeof(KeyObject),
+       tp_flags:           Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+       tp_new:             Key_new,
+       tp_dealloc:         (destructor)Key_dealloc,
+       tp_init:            (initproc)Key_init,
+       tp_doc:             "Key object",
+       tp_methods:         Key_methods,
+       //tp_getset:          Key_getsetters,
+       tp_repr:            (reprfunc)Key_repr,
+       tp_str:             (reprfunc)Key_str,
+};
diff --git a/src/_pakfire/key.h b/src/_pakfire/key.h
new file mode 100644 (file)
index 0000000..9ffbe9a
--- /dev/null
@@ -0,0 +1,40 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2017 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef PYTHON_PAKFIRE_KEY_H
+#define PYTHON_PAKFIRE_KEY_H
+
+#include <Python.h>
+
+#include <pakfire/key.h>
+
+#include "pool.h"
+
+typedef struct {
+       PyObject_HEAD
+       PoolObject* pool;
+       PakfireKey key;
+} KeyObject;
+
+extern PyTypeObject KeyType;
+
+PyObject* new_key(PoolObject* pool, PakfireKey key);
+
+#endif /* PYTHON_PAKFIRE_KEY_H */
index 3c0fc820698fbc6f63ad724b923b75025f21b469..2fc42dbd881759843a5f260af80b4db7d0e17654 100644 (file)
 #include <solv/solver.h>
 
 #include <pakfire/errno.h>
+#include <pakfire/key.h>
 #include <pakfire/pool.h>
 #include <pakfire/repo.h>
 
 #include "constants.h"
+#include "key.h"
 #include "pool.h"
 #include "relation.h"
 #include "repo.h"
@@ -202,7 +204,61 @@ static PyObject* Pool_search(PoolObject* self, PyObject* args) {
        return PyList_FromPackageList(self, list);
 }
 
+static PyObject* Pool_get_keys(PoolObject* self) {
+       PyObject* list = PyList_New(0);
+
+       PakfireKey* keys = pakfire_key_list(self->pool);
+       while (keys && *keys) {
+               PakfireKey key = *keys++;
+
+               PyObject* object = new_key(self, key);
+               PyList_Append(list, object);
+               Py_DECREF(object);
+
+               pakfire_key_free(key);
+       }
+
+       return list;
+}
+
+static PyObject* Pool_get_key(PoolObject* self, PyObject* args) {
+       const char* pattern = NULL;
+
+       if (!PyArg_ParseTuple(args, "s", &pattern))
+               return NULL;
+
+       PakfireKey key = pakfire_key_get(self->pool, pattern);
+       if (!key)
+               Py_RETURN_NONE;
+
+       return new_key(self, key);
+}
+
+static PyObject* Pool_generate_key(PoolObject* self, PyObject* args) {
+       const char* userid = NULL;
+
+       if (!PyArg_ParseTuple(args, "s", &userid))
+               return NULL;
+
+       PakfireKey key = pakfire_key_generate(self->pool, userid);
+       assert(key);
+
+       return new_key(self, key);
+}
+
 static struct PyMethodDef Pool_methods[] = {
+       {
+               "generate_key",
+               (PyCFunction)Pool_generate_key,
+               METH_VARARGS,
+               NULL
+       },
+       {
+               "get_key",
+               (PyCFunction)Pool_get_key,
+               METH_VARARGS,
+               NULL
+       },
        {
                "search",
                (PyCFunction)Pool_search,
@@ -246,6 +302,13 @@ static struct PyGetSetDef Pool_getsetters[] = {
                NULL,
                NULL
        },
+       {
+               "keys",
+               (getter)Pool_get_keys,
+               NULL,
+               NULL,
+               NULL
+       },
        { NULL }
 };
 
diff --git a/src/libpakfire/include/pakfire/key.h b/src/libpakfire/include/pakfire/key.h
new file mode 100644 (file)
index 0000000..ee86118
--- /dev/null
@@ -0,0 +1,53 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2017 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef PAKFIRE_KEY_H
+#define PAKFIRE_KEY_H
+
+#include <gpgme.h>
+
+#include <pakfire/types.h>
+
+typedef enum pakfire_key_export_mode {
+       PAKFIRE_KEY_EXPORT_MODE_PUBLIC = 0,
+       PAKFIRE_KEY_EXPORT_MODE_SECRET,
+} pakfire_key_export_mode_t;
+
+PakfireKey* pakfire_key_list(PakfirePool pool);
+
+PakfireKey pakfire_key_create(PakfirePool pool, gpgme_key_t gpgkey);
+void pakfire_key_free(PakfireKey key);
+
+PakfireKey pakfire_key_get(PakfirePool pool, const char* fingerprint);
+const char* pakfire_key_get_fingerprint(PakfireKey key);
+PakfireKey pakfire_key_generate(PakfirePool pool, const char* userid);
+char* pakfire_key_export(PakfireKey key, pakfire_key_export_mode_t mode);
+
+#ifdef PAKFIRE_PRIVATE
+
+struct _PakfireKey {
+       PakfirePool pool;
+       gpgme_key_t gpgkey;
+       int nrefs;
+};
+
+#endif
+
+#endif /* PAKFIRE_KEY_H */
index 26c01357f0653f8af044f13e56e11534b3d9f810..feb69e2c36fe7bcb3c29fee0548af9d6df22f84f 100644 (file)
@@ -25,6 +25,7 @@ typedef struct _PakfireArchive* PakfireArchive;
 typedef struct _PakfireCache* PakfireCache;
 typedef struct _PakfireFile* PakfireFile;
 typedef struct _PakfireFilter* PakfireFilter;
+typedef struct _PakfireKey* PakfireKey;
 typedef struct _PakfirePackage* PakfirePackage;
 typedef struct _PakfirePackageCache* PakfirePackageCache;
 typedef struct _PakfirePackageList* PakfirePackageList;
diff --git a/src/libpakfire/key.c b/src/libpakfire/key.c
new file mode 100644 (file)
index 0000000..fa45d71
--- /dev/null
@@ -0,0 +1,231 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2017 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <assert.h>
+#include <gpgme.h>
+
+#include <pakfire/key.h>
+#include <pakfire/pool.h>
+#include <pakfire/util.h>
+
+static gpgme_ctx_t pakfire_get_gpgctx(PakfirePool pool) {
+       static int gpg_initialized = 0;
+       gpgme_error_t error;
+       const char* error_string;
+
+       if (!gpg_initialized) {
+               // Initialise gpgme
+               const char* version = gpgme_check_version(NULL);
+               assert(version);
+#if 0
+               printf("version = %s\n", version);
+#endif
+
+               // Check if we support GPG
+               error = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
+               if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+                       goto FAIL;
+
+               // Use GPG
+               error = gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP,
+                       NULL, "/etc/pakfire/gnupg");
+               if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+                       goto FAIL;
+
+               gpgme_engine_info_t engine_info;
+               error = gpgme_get_engine_info(&engine_info);
+               if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+                       goto FAIL;
+
+#if 0
+               printf("GPGME engine info: %s, %s\n",
+                       engine_info->file_name, engine_info->home_dir);
+#endif
+
+               // GPG has been initialized
+               gpg_initialized++;              
+       }
+
+       // Create a new context
+       gpgme_ctx_t ctx;
+       error = gpgme_new(&ctx);
+       if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+               goto FAIL;
+
+       // Set output to be ASCII armoured
+       gpgme_set_armor(ctx, 1);
+
+       return ctx;
+
+FAIL:
+       error_string = gpgme_strerror(error);
+       printf("ERROR: %s\n", error_string);
+
+       return NULL;
+}
+
+PakfireKey* pakfire_key_list(PakfirePool pool) {
+       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pool);
+       assert(gpgctx);
+
+       PakfireKey* first = pakfire_calloc(1, sizeof(PakfireKey));
+       PakfireKey* list = first;
+
+       gpgme_key_t gpgkey = NULL;
+       gpgme_error_t error = gpgme_op_keylist_start(gpgctx, NULL, 0);
+       while (!error) {
+               error = gpgme_op_keylist_next(gpgctx, &gpgkey);
+               if (error)
+                       break;
+
+               // Add key to the list
+               *list++ = pakfire_key_create(pool, gpgkey);
+
+               gpgme_key_release(gpgkey);
+       }
+
+       // Last list item must be NULL
+       *list = NULL;
+
+       return first;
+}
+
+PakfireKey pakfire_key_create(PakfirePool pool, gpgme_key_t gpgkey) {
+       PakfireKey key = pakfire_calloc(1, sizeof(*key));
+
+       if (key) {
+               key->pool = pool;
+
+               key->gpgkey = gpgkey;
+               gpgme_key_ref(key->gpgkey);
+       }
+
+       return key;
+}
+
+void pakfire_key_free(PakfireKey key) {
+       gpgme_key_unref(key->gpgkey);
+
+       pakfire_free(key);
+}
+
+PakfireKey pakfire_key_get(PakfirePool pool, const char* fingerprint) {
+       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pool);
+       assert(gpgctx);
+
+       gpgme_key_t gpgkey = NULL;
+       gpgme_error_t error = gpgme_get_key(gpgctx, fingerprint, &gpgkey, 1);
+       if (error != GPG_ERR_NO_ERROR)
+               return NULL;
+
+       PakfireKey key = pakfire_key_create(pool, gpgkey);
+       gpgme_key_unref(gpgkey);
+       gpgme_release(gpgctx);
+
+       return key;
+}
+
+const char* pakfire_key_get_fingerprint(PakfireKey key) {
+       return key->gpgkey->fpr;
+}
+
+PakfireKey pakfire_key_generate(PakfirePool pool, const char* userid) {
+       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pool);
+       assert(gpgctx);
+
+       unsigned int flags = 0;
+
+       // Key should be able to be used to sign
+       flags |= GPGME_CREATE_SIGN;
+
+       // Don't set a password
+       flags |= GPGME_CREATE_NOPASSWD;
+
+       // The key should never expire
+       flags |= GPGME_CREATE_NOEXPIRE;
+
+       // Generate the key
+       gpgme_error_t error = gpgme_op_createkey(gpgctx, userid,
+               "rsa512", 0, 0, NULL, flags);
+
+       if (error != GPG_ERR_NO_ERROR) {
+               printf("ERROR: %s\n", gpgme_strerror(error));
+               return NULL;
+       }
+
+       // Retrieve the result
+       gpgme_genkey_result_t result = gpgme_op_genkey_result(gpgctx);
+       gpgme_release(gpgctx);
+
+       // Retrieve the key by its fingerprint
+       return pakfire_key_get(pool, result->fpr);
+}
+
+char* pakfire_key_export(PakfireKey key, pakfire_key_export_mode_t mode) {
+       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(key->pool);
+       assert(gpgctx);
+
+       gpgme_export_mode_t gpgmode = 0;
+       switch (mode) {
+               case PAKFIRE_KEY_EXPORT_MODE_SECRET:
+                       gpgmode |= GPGME_EXPORT_MODE_SECRET;
+                       break;
+       
+               default:
+                       break;
+       }
+
+       const char* fingerprint = pakfire_key_get_fingerprint(key);
+
+       // Initialize the buffer
+       gpgme_data_t keydata;
+       gpgme_error_t error = gpgme_data_new(&keydata);
+       if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+               goto FAIL;
+
+       // Encode output as ASCII
+       error = gpgme_data_set_encoding(keydata, GPGME_DATA_ENCODING_ARMOR);
+       if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+               goto FAIL;
+
+       // Copy the key to the buffer
+       error = gpgme_op_export(gpgctx, fingerprint, gpgmode, keydata);
+       if (gpg_err_code(error) != GPG_ERR_NO_ERROR)
+               goto FAIL;
+
+       // Export key in ASCII format
+       size_t length;
+       char* mem = gpgme_data_release_and_get_mem(keydata, &length);
+       gpgme_release(gpgctx);
+
+       // Copy to our own string buffer
+       char* buffer = pakfire_strdup(mem);
+
+       // Release the exported key
+       gpgme_free(mem);
+
+       return buffer;
+
+FAIL:
+       gpgme_data_release(keydata);
+       gpgme_release(gpgctx);
+
+       return NULL;
+}
index fe05fc7eefac08d9bfaaf61a78a41b6d3bb1ed54..f6831e80083a8563a9bfe7dd9972a2af2d5e9e78 100644 (file)
@@ -61,6 +61,15 @@ global:
        pakfire_file_sort;
        pakfire_file_swap;
 
+       # key
+       pakfire_key_create;
+       pakfire_key_export;
+       pakfire_key_free;
+       pakfire_key_generate;
+       pakfire_key_get;
+       pakfire_key_get_fingerprint;
+       pakfire_key_list;
+
        # package
        pakfire_package_add_conflicts;
        pakfire_package_add_obsoletes;
index 9b7e82ab143963e394eb1efef958b03d26132866..e2e9c09ee63bd0a3b57bdddd7f9342b305b14818 100644 (file)
@@ -26,7 +26,7 @@ import string
 from . import _pakfire
 from . import distro
 from . import filelist
-from . import keyring
+#from . import keyring
 from . import packages
 from . import repository
 from . import transaction
@@ -66,7 +66,7 @@ class Pakfire(object):
                self.config = config or Config("general.conf")
 
                # Initialize the keyring
-               self.keyring = keyring.Keyring(self)
+               #self.keyring = keyring.Keyring(self)
 
                self.pool = _pakfire.Pool(self.arch.name)
                self.pool.cache_path = cache_path or \
index f1382e23bfb2f9887f7ca1254ee4e5750922fb73..3475fac5a21986d9bdbc6561dceeedf03cd01183 100644 (file)
@@ -766,41 +766,37 @@ class CliDaemon(Cli):
 
 
 class CliKey(Cli):
-       pakfire = base.PakfireKey
-
-       def __init__(self):
-               self.parser = argparse.ArgumentParser(
-                       description = _("Pakfire key command line interface."),
+       def parse_cli(self):
+               parser = argparse.ArgumentParser(
+                       description = _("Pakfire key command line interface"),
                )
-               self._add_common_arguments(self.parser, offline_switch=True)
-
-               # Add sub-commands.
-               self.sub_commands = self.parser.add_subparsers()
-
-               self.parse_command_generate()
-               self.parse_command_import()
-               self.parse_command_export()
-               self.parse_command_delete()
-               self.parse_command_list()
-               self.parse_command_sign()
-               self.parse_command_verify()
+               subparsers = parser.add_subparsers()
 
-               # Finally parse all arguments from the command line and save them.
-               self.args = self.parser.parse_args()
+               # Add common arguments
+               self._add_common_arguments(parser)
 
-               self.action2func = {
-                       "generate"    : self.handle_generate,
-                       "import"      : self.handle_import,
-                       "export"      : self.handle_export,
-                       "delete"      : self.handle_delete,
-                       "list"        : self.handle_list,
-                       "sign"        : self.handle_sign,
-                       "verify"      : self.handle_verify,
-               }
+               # generate
+               generate = subparsers.add_parser("generate", help=_("Import a key from file"))
+               generate.add_argument("--realname", nargs=1,
+                       help=_("The real name of the owner of this key"))
+               generate.add_argument("--email", nargs=1,
+                       help=_("The email address of the owner of this key"))
+               generate.set_defaults(func=self.handle_generate)
+
+               # list
+               list = subparsers.add_parser("list", help=_("List all imported keys"))
+               list.set_defaults(func=self.handle_list)
+
+               # export
+               export = subparsers.add_parser("export", help=_("Export a key to a file"))
+               export.add_argument("fingerprint", nargs=1,
+                       help=_("The fingerprint of the key to export"))
+               export.add_argument("--filename", nargs="*", help=_("Write the key to this file"))
+               export.add_argument("--secret", action="store_true",
+                       help=_("Export the secret key"))
+               export.set_defaults(func=self.handle_export)
 
-       @property
-       def pakfire_args(self):
-               return {}
+               return parser.parse_args()
 
        def parse_command_generate(self):
                # Parse "generate" command.
@@ -810,7 +806,7 @@ class CliKey(Cli):
                        help=_("The real name of the owner of this key."))
                sub_gen.add_argument("--email", nargs=1,
                        help=_("The email address of the owner of this key."))
-               sub_gen.add_argument("action", action="store_const", const="generate")
+               sub_gen.set_defaults(func=self.handle_generate)
 
        def parse_command_import(self):
                # Parse "import" command.
@@ -820,16 +816,6 @@ class CliKey(Cli):
                        help=_("Filename of that key to import."))
                sub_import.add_argument("action", action="store_const", const="import")
 
-       def parse_command_export(self):
-               # Parse "export" command.
-               sub_export = self.sub_commands.add_parser("export",
-                       help=_("Export a key to a file."))
-               sub_export.add_argument("keyid", nargs=1,
-                       help=_("The ID of the key to export."))
-               sub_export.add_argument("filename", nargs=1,
-                       help=_("Write the key to this file."))
-               sub_export.add_argument("action", action="store_const", const="export")
-
        def parse_command_delete(self):
                # Parse "delete" command.
                sub_del = self.sub_commands.add_parser("delete",
@@ -838,12 +824,6 @@ class CliKey(Cli):
                        help=_("The ID of the key to delete."))
                sub_del.add_argument("action", action="store_const", const="delete")
 
-       def parse_command_list(self):
-               # Parse "list" command.
-               sub_list = self.sub_commands.add_parser("list",
-                       help=_("List all imported keys."))
-               sub_list.add_argument("action", action="store_const", const="list")
-
        def parse_command_sign(self):
                # Implement the "sign" command.
                sub_sign = self.sub_commands.add_parser("sign",
@@ -864,16 +844,36 @@ class CliKey(Cli):
                        help=_("Package(s) to verify."))
                sub_verify.add_argument("action", action="store_const", const="verify")
 
-       def handle_generate(self):
-               realname = self.args.realname[0]
-               email    = self.args.email[0]
+       def handle_generate(self, ns):
+               p = self.pakfire(ns)
 
                print(_("Generating the key may take a moment..."))
                print()
 
-               # Generate the key.
-               p = self.create_pakfire()
-               p.keyring.gen_key(realname, email)
+               key = p.pool.generate_key("%s <%s>" % (ns.realname.pop(), ns.email.pop()))
+
+       def handle_list(self, ns):
+               p = self.pakfire(ns)
+
+               for key in p.pool.keys:
+                       print(key)
+
+       def handle_export(self, ns):
+               p = self.pakfire(ns)
+
+               for fingerprint in ns.fingerprint:
+                       key = p.pool.get_key(fingerprint)
+                       if not key:
+                               print(_("Could not find key with fingerprint %s") % fingerprint)
+                               continue
+
+                       data = key.export(ns.secret)
+
+                       for file in ns.filename:
+                               with open(file, "w") as f:
+                                       f.write(data)
+                       else:
+                               print(data)
 
        def handle_import(self):
                filename = self.args.filename[0]
@@ -882,24 +882,12 @@ class CliKey(Cli):
                p = self.create_pakfire()
                p.keyring.import_key(filename)
 
-       def handle_export(self):
-               keyid    = self.args.keyid[0]
-               filename = self.args.filename[0]
-
-               p = self.create_pakfire()
-               p.keyring.export_key(keyid, filename)
-
        def handle_delete(self):
                keyid = self.args.keyid[0]
 
                p = self.create_pakfire()
                p.keyring.delete_key(keyid)
 
-       def handle_list(self):
-               p = self.create_pakfire()
-               for line in p.keyring.list_keys():
-                       print(line)
-
        def handle_sign(self):
                # Get the files from the command line options
                files = []