]> git.ipfire.org Git - people/ms/pakfire.git/commitdiff
keys: Replace usage of PGP by signify
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 12:40:55 +0000 (12:40 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Jun 2023 12:41:39 +0000 (12:41 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
17 files changed:
Makefile.am
configure.ac
src/_pakfire/key.c
src/_pakfire/pakfire.c
src/libpakfire/include/pakfire/key.h
src/libpakfire/include/pakfire/pakfire.h
src/libpakfire/include/pakfire/util.h
src/libpakfire/key.c
src/libpakfire/keystore.c
src/libpakfire/libpakfire.sym
src/libpakfire/pakfire.c
src/libpakfire/repo.c
src/libpakfire/util.c
tests/data/keys/key1.pub [new file with mode: 0644]
tests/data/keys/key1.sec [new file with mode: 0644]
tests/libpakfire/key.c
tests/libpakfire/key.h [deleted file]

index 5e6dd36fa2e100973d8bdc14f9f9bcd09855efb8..03cc312ac0c63d213dfbe262a20b6f91ad0c9194 100644 (file)
@@ -337,7 +337,6 @@ libpakfire_la_LIBADD = \
        $(CAP_LIBS) \
        $(CURL_LIBS) \
        $(ELF_LIBS) \
-       $(GPGME_LIBS) \
        $(JSON_C_LIBS) \
        $(LZMA_LIBS) \
        $(MAGIC_LIBS) \
@@ -565,8 +564,7 @@ tests_libpakfire_jail_LDADD = \
        $(TESTSUITE_LDADD)
 
 tests_libpakfire_key_SOURCES = \
-       tests/libpakfire/key.c \
-       tests/libpakfire/key.h
+       tests/libpakfire/key.c
 
 tests_libpakfire_key_CPPFLAGS = \
        $(TESTSUITE_CPPFLAGS)
@@ -883,6 +881,7 @@ TESTSUITE_CPPFLAGS = \
        $(AM_CPPFLAGS) \
        $(PAKFIRE_CPPFLAGS) \
        -DABS_TOP_SRCDIR=\"$(abs_top_srcdir)\" \
+       -DTEST_DATA_DIR=\"$(abs_top_srcdir)/tests/data\" \
        -DTEST_ROOTFS=\"$(TEST_ROOTFS)\" \
        -DTEST_STUB_COMMAND=\"$(abs_top_builddir)/tests/stub/root/command\" \
        -DTEST_STUB_ROOT=\"$(TEST_STUB_ROOT)\" \
@@ -926,6 +925,9 @@ EXTRA_DIST += \
        \
        tests/data/digest/random \
        \
+       tests/data/keys/key1.pub \
+       tests/data/keys/key1.sec \
+       \
        tests/data/packages/dummy/dummy.nm \
        \
        tests/data/parser/test-comments.txt \
index 467fbad5636b3c605681054daae7316042ae02dc..414b2885b2e77cdc5eb8d4d54d247ecebce52bce 100644 (file)
@@ -256,7 +256,6 @@ PKG_CHECK_MODULES([ARCHIVE], [libarchive >= 3.4.0])
 PKG_CHECK_MODULES([CAP], [libcap])
 PKG_CHECK_MODULES([CURL], [libcurl])
 PKG_CHECK_MODULES([ELF], [libelf])
-PKG_CHECK_MODULES([GPGME], [gpgme >= 1.6.0])
 PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}-embed],
        [], [PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}])])
 PKG_CHECK_MODULES([JSON_C], [json-c >= 0.15])
index e7c6f52b3220da963d6e63d47bb57d05c44ab298..73083171abd8316c25b9578eb3c1511cd850771b 100644 (file)
@@ -52,24 +52,10 @@ static void Key_dealloc(KeyObject* self) {
        Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
-static int Key_init(KeyObject* self, PyObject* args, PyObject* kwds) {
-       PakfireObject* pakfire;
-       const char* fingerprint = NULL;
-
-       if (!PyArg_ParseTuple(args, "O!s", &PakfireType, &pakfire, &fingerprint))
-               return -1;
-
-       self->key = pakfire_key_get(pakfire->pakfire, fingerprint);
-       if (!self->key)
-               return -1;
-
-       return 0;
-}
-
 static PyObject* Key_repr(KeyObject* self) {
-       const char* fingerprint = pakfire_key_get_fingerprint(self->key);
+       const char* id = pakfire_key_get_id(self->key);
 
-       return PyUnicode_FromFormat("<_pakfire.Key (%s)>", fingerprint);
+       return PyUnicode_FromFormat("<_pakfire.Key (%s)>", id);
 }
 
 static PyObject* Key_str(KeyObject* self) {
@@ -81,80 +67,28 @@ static PyObject* Key_str(KeyObject* self) {
        return object;
 }
 
-static PyObject* Key_get_created_at(KeyObject* self) {
-       const time_t t = pakfire_key_get_created(self->key);
-
-       return PyDateTime_FromTime_t(&t);
-}
-
-static PyObject* Key_get_expires_at(KeyObject* self) {
-       const time_t t = pakfire_key_get_expires(self->key);
-
-       // Return None if the key does not expire
-       if (!t)
-               Py_RETURN_NONE;
-
-       return PyDateTime_FromTime_t(&t);
-}
-
-static PyObject* Key_get_fingerprint(KeyObject* self) {
-       const char* fingerprint = pakfire_key_get_fingerprint(self->key);
-
-       return PyUnicode_FromString(fingerprint);
-}
-
-static PyObject* Key_get_uid(KeyObject* self) {
-       const char* uid = pakfire_key_get_uid(self->key);
-
-       // Raise an error on no input
-       if (!uid) {
-               PyErr_SetFromErrno(PyExc_OSError);
-               return NULL;
-       }
-
-       return PyUnicode_FromString(uid);
-}
-
-static PyObject* Key_get_name(KeyObject* self) {
-       const char* name = pakfire_key_get_name(self->key);
-
-       // Raise an error on no input
-       if (!name) {
-               PyErr_SetFromErrno(PyExc_OSError);
-               return NULL;
-       }
-
-       return PyUnicode_FromString(name);
-}
-
-static PyObject* Key_get_email(KeyObject* self) {
-       const char* email = pakfire_key_get_email(self->key);
+static PyObject* Key_get_id(KeyObject* self) {
+       const char* id = pakfire_key_get_id(self->key);
 
        // Raise an error on no input
-       if (!email) {
+       if (!id) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
        }
 
-       return PyUnicode_FromString(email);
+       return PyUnicode_FromString(id);
 }
 
-static PyObject* Key_get_algo(KeyObject* self) {
-       const char* algo = pakfire_key_get_pubkey_algo(self->key);
+static PyObject* Key_get_algorithm(KeyObject* self) {
+       const char* algorithm = pakfire_key_get_algo(self->key);
 
        // Raise an error on no input
-       if (!algo) {
+       if (algorithm) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
        }
 
-       return PyUnicode_FromString(algo);
-}
-
-static PyObject* Key_get_length(KeyObject* self) {
-       const size_t length = pakfire_key_get_pubkey_length(self->key);
-
-       return PyLong_FromLong(length);
+       return PyUnicode_FromString(algorithm);
 }
 
 static PyObject* Key_export(KeyObject* self, PyObject* args) {
@@ -178,7 +112,7 @@ static PyObject* Key_export(KeyObject* self, PyObject* args) {
 
        pakfire_key_export_mode_t mode;
        if (secret)
-               mode = PAKFIRE_KEY_EXPORT_MODE_SECRET;
+               mode = PAKFIRE_KEY_EXPORT_MODE_PRIVATE;
        else
                mode = PAKFIRE_KEY_EXPORT_MODE_PUBLIC;
 
@@ -200,54 +134,6 @@ static PyObject* Key_delete(KeyObject* self) {
        return NULL;
 }
 
-static PyObject* Key_get_public_key(KeyObject* self) {
-       char* buffer = NULL;
-       size_t length = 0;
-       int r;
-
-       PyObject* object = NULL;
-
-       // Fetch the public key
-       r = pakfire_key_get_public_key(self->key, &buffer, &length);
-       if (r) {
-               PyErr_SetFromErrno(PyExc_OSError);
-               goto ERROR;
-       }
-
-       // Create a unicode object
-       object = PyUnicode_FromStringAndSize(buffer, length);
-
-ERROR:
-       if (buffer)
-               free(buffer);
-
-       return object;
-}
-
-static PyObject* Key_get_secret_key(KeyObject* self) {
-       char* buffer = NULL;
-       size_t length = 0;
-       int r;
-
-       PyObject* object = NULL;
-
-       // Fetch the secret key
-       r = pakfire_key_get_secret_key(self->key, &buffer, &length);
-       if (r) {
-               PyErr_SetFromErrno(PyExc_OSError);
-               goto ERROR;
-       }
-
-       // Create a unicode object
-       object = PyUnicode_FromStringAndSize(buffer, length);
-
-ERROR:
-       if (buffer)
-               free(buffer);
-
-       return object;
-}
-
 static struct PyMethodDef Key_methods[] = {
        {
                "delete",
@@ -266,71 +152,15 @@ static struct PyMethodDef Key_methods[] = {
 
 static struct PyGetSetDef Key_getsetters[] = {
        {
-               "algo",
-               (getter)Key_get_algo,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "created_at",
-               (getter)Key_get_created_at,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "email",
-               (getter)Key_get_email,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "expires_at",
-               (getter)Key_get_expires_at,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "fingerprint",
-               (getter)Key_get_fingerprint,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "length",
-               (getter)Key_get_length,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "name",
-               (getter)Key_get_name,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "public_key",
-               (getter)Key_get_public_key,
-               NULL,
-               NULL,
-               NULL,
-       },
-       {
-               "secret_key",
-               (getter)Key_get_secret_key,
+               "algorithm",
+               (getter)Key_get_algorithm,
                NULL,
                NULL,
                NULL,
        },
        {
-               "uid",
-               (getter)Key_get_uid,
+               "id",
+               (getter)Key_get_id,
                NULL,
                NULL,
                NULL,
@@ -345,7 +175,6 @@ PyTypeObject KeyType = {
        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,
index 811206cd3082d56520d085350e02e4ee9a5595ef..764e3eb1f1e8bddad76dc9bc89b87791badda463 100644 (file)
@@ -641,34 +641,16 @@ static PyObject* Pakfire_get_keys(PakfireObject* self) {
        return list;
 }
 
-static PyObject* Pakfire_get_key(PakfireObject* self, PyObject* args) {
-       const char* pattern = NULL;
-
-       if (!PyArg_ParseTuple(args, "s", &pattern))
-               return NULL;
-
-       // Try finding the key
-       struct pakfire_key* key = pakfire_key_get(self->pakfire, pattern);
-       if (!key)
-               Py_RETURN_NONE;
-
-       PyObject* object = new_key(&KeyType, key);
-       pakfire_key_unref(key);
-
-       return object;
-}
-
 static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args, PyObject* kwds) {
-       char* kwlist[] = { "userid", "algorithm", NULL };
+       char* kwlist[] = { "algorithm", NULL };
        struct pakfire_key* key = NULL;
-       const char* userid = NULL;
-       const char* algo = NULL;
+       pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_NULL;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|$z", kwlist, &userid, &algo))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &algo))
                return NULL;
 
        // Generate a new key
-       int r = pakfire_key_generate(&key, self->pakfire, algo, userid);
+       int r = pakfire_key_generate(&key, self->pakfire, algo);
        if (r) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
@@ -680,44 +662,6 @@ static PyObject* Pakfire_generate_key(PakfireObject* self, PyObject* args, PyObj
        return object;
 }
 
-static PyObject* Pakfire_import_key(PakfireObject* self, PyObject* args) {
-       PyObject* object = NULL;
-
-       if (!PyArg_ParseTuple(args, "O", &object))
-               return NULL;
-
-       // Get a file descriptor from object
-       int fd = PyObject_AsFileDescriptor(object);
-       if (fd < 0)
-               return NULL;
-
-       // Convert to FILE*
-       FILE* f = fdopen(fd, "r");
-       if (!f) {
-               PyErr_SetFromErrno(PyExc_OSError);
-               return NULL;
-       }
-
-       struct pakfire_key** keys = NULL;
-
-       // Import keys from f
-       int r = pakfire_key_import(self->pakfire, f, &keys);
-       if (r) {
-               PyErr_SetFromErrno(PyExc_OSError);
-               return NULL;
-       }
-
-       // Convert keys to list
-       PyObject* list = Pakfire_keys_to_list(keys);
-
-       // Free keys
-       for (struct pakfire_key** key = keys; *key; key++)
-               pakfire_key_unref(*key);
-       free(keys);
-
-       return list;
-}
-
 static PyObject* Pakfire_whatprovides(PakfireObject* self, PyObject* args) {
        const char* provides = NULL;
        struct pakfire_packagelist* list = NULL;
@@ -1584,24 +1528,12 @@ static struct PyMethodDef Pakfire_methods[] = {
                METH_VARARGS|METH_KEYWORDS,
                NULL
        },
-       {
-               "get_key",
-               (PyCFunction)Pakfire_get_key,
-               METH_VARARGS,
-               NULL
-       },
        {
                "get_repo",
                (PyCFunction)Pakfire_get_repo,
                METH_VARARGS,
                NULL
        },
-       {
-               "import_key",
-               (PyCFunction)Pakfire_import_key,
-               METH_VARARGS,
-               NULL
-       },
        {
                "install",
                (PyCFunction)Pakfire_install,
index 139bc63ca0b22c48e5cb2190d10c55bbe036f9c2..a083335cfd0e9e17eec63742f911cdbf14672cfe 100644 (file)
@@ -27,52 +27,39 @@ struct pakfire_key;
 
 #include <pakfire/pakfire.h>
 
+typedef enum pakfire_key_algos {
+       PAKFIRE_KEY_ALGO_NULL = 0,
+       PAKFIRE_KEY_ALGO_ED25519,
+} pakfire_key_algo_t;
+
 typedef enum pakfire_key_export_mode {
        PAKFIRE_KEY_EXPORT_MODE_PUBLIC = 0,
-       PAKFIRE_KEY_EXPORT_MODE_SECRET,
+       PAKFIRE_KEY_EXPORT_MODE_PRIVATE,
 } pakfire_key_export_mode_t;
 
 struct pakfire_key* pakfire_key_ref(struct pakfire_key* key);
 void pakfire_key_unref(struct pakfire_key* key);
 
-int pakfire_key_fetch(struct pakfire_key** key, struct pakfire* pakfire,
-       const char* uid, const char* fingerprint);
-
-struct pakfire_key* pakfire_key_get(struct pakfire* pakfire, const char* fingerprint);
 int pakfire_key_delete(struct pakfire_key* key);
 
 // Access key properties
-const char* pakfire_key_get_fingerprint(struct pakfire_key* key);
-const char* pakfire_key_get_uid(struct pakfire_key* key);
-const char* pakfire_key_get_name(struct pakfire_key* key);
-const char* pakfire_key_get_email(struct pakfire_key* key);
-const char* pakfire_key_get_pubkey_algo(struct pakfire_key* key);
-size_t pakfire_key_get_pubkey_length(struct pakfire_key* key);
-int pakfire_key_has_secret(struct pakfire_key* key);
-time_t pakfire_key_get_created(struct pakfire_key* key);
-time_t pakfire_key_get_expires(struct pakfire_key* key);
-int pakfire_key_is_revoked(struct pakfire_key* key);
+const char* pakfire_key_get_id(struct pakfire_key* key);
+const char* pakfire_key_get_algo(struct pakfire_key* key);
 
 int pakfire_key_generate(struct pakfire_key** key, struct pakfire* pakfire,
-       const char* algo, const char* userid);
-int pakfire_key_export(struct pakfire_key* key, FILE* f, pakfire_key_export_mode_t mode);
-int pakfire_key_import(struct pakfire* pakfire, FILE* f, struct pakfire_key*** keys);
-
-int pakfire_key_get_public_key(struct pakfire_key* key, char** buffer, size_t* length);
-int pakfire_key_get_secret_key(struct pakfire_key* key, char** buffer, size_t* length);
+       const pakfire_key_algo_t algo);
+int pakfire_key_export(struct pakfire_key* key, FILE* f, const pakfire_key_export_mode_t mode);
+int pakfire_key_import(struct pakfire_key** key, struct pakfire* pakfire, FILE* f);
 
 char* pakfire_key_dump(struct pakfire_key* key);
 
 #ifdef PAKFIRE_PRIVATE
 
-#include <gpgme.h>
-
-#define PAKFIRE_KEY_FPR_MAXLEN 41
-
-int pakfire_key_create(struct pakfire_key** key, struct pakfire* pakfire, gpgme_key_t gpgkey);
+int pakfire_key_import_from_string(struct pakfire_key** key,
+       struct pakfire* pakfire, const char* data, const size_t length);
 
-int pakfire_key_sign(struct pakfire_key* key, const char* buffer, const size_t buffer_length,
-       char** signature, size_t* signature_length, time_t* timestamp);
+int pakfire_key_sign(struct pakfire_key* key,
+       FILE* f, const char* data, const size_t length, const char* comment);
 
 #endif
 
index c58b16ba51b496f3bc2181921806f6094e0e1cd2..9950161efcf9e0f4d6dff09fca27aa9f4070c82b 100644 (file)
@@ -120,7 +120,6 @@ int pakfire_sync(struct pakfire* pakfire, int solver_flags, int flags, int* chan
 
 #include <sys/types.h>
 
-#include <gpgme.h>
 #include <magic.h>
 #include <solv/pool.h>
 
@@ -151,7 +150,6 @@ int pakfire_is_mountpoint(struct pakfire* pakfire, const char* path);
 int pakfire_confirm(struct pakfire* pakfire, const char* message, const char* question);
 
 magic_t pakfire_get_magic(struct pakfire* pakfire);
-gpgme_ctx_t pakfire_get_gpgctx(struct pakfire* pakfire);
 
 const char* pakfire_get_distro_name(struct pakfire* pakfire);
 const char* pakfire_get_distro_id(struct pakfire* pakfire);
@@ -160,8 +158,6 @@ const char* pakfire_get_distro_version(struct pakfire* pakfire);
 const char* pakfire_get_distro_version_id(struct pakfire* pakfire);
 const char* pakfire_get_distro_tag(struct pakfire* pakfire);
 
-const char* pakfire_get_keystore_path(struct pakfire* pakfire);
-
 #define pakfire_path(pakfire, path, format, ...) \
        __pakfire_path(pakfire, path, sizeof(path), format, __VA_ARGS__)
 int __pakfire_path(struct pakfire* pakfire, char* path, const size_t length,
index d9a1505d53646cc3348b18b386d034def9d6de1f..fee3ab311f7cd6a2d88ae833f7fa086796831dd0 100644 (file)
@@ -121,6 +121,11 @@ int pakfire_rlimit_reset_nofile(struct pakfire* pakfire);
 int pakfire_compile_regex(struct pakfire* pakfire, pcre2_code** regex,
        const char* pattern);
 
+// Base64
+
+int pakfire_b64encode(struct pakfire* pakfire, char** output,
+       const void* buffer, const size_t length);
+
 #endif
 
 #endif /* PAKFIRE_UTIL_H */
index f10527d34105c9627c270c850b279f28d999b721..d7a07c95e5dffbe2b59ea0e5be18881ec5cc6249 100644 (file)
 #############################################################################*/
 
 #include <errno.h>
-#include <gpgme.h>
 #include <linux/limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
+// OpenSSL
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/rand.h>
+
 #include <pakfire/constants.h>
 #include <pakfire/i18n.h>
 #include <pakfire/key.h>
 #include <pakfire/string.h>
 #include <pakfire/util.h>
 
+// Size of the buffer to allocate for error messages
+#define ERROR_MAX              1024
+
+typedef unsigned char pakfire_key_id[8];
+
 struct pakfire_key {
        struct pakfire* pakfire;
        int nrefs;
 
-       gpgme_key_t gpgkey;
+       // Algorithm
+       pakfire_key_algo_t algo;
+
+       // Key ID
+       pakfire_key_id id;
+
+       // The public (or private) key
+       EVP_PKEY* pkey;
+};
+
+struct pakfire_key_public_key {
+       unsigned char sig_algo[2];
+       pakfire_key_id id;
+       unsigned char pubkey[32];
+};
+
+struct pakfire_key_private_key {
+       unsigned char sig_algo[2];
+    unsigned char kdf_algo[2];
+       uint32_t kdf_rounds;
+    unsigned char kdf_salt[16];
+       unsigned char checksum[8];
+       pakfire_key_id id;
+       struct {
+               unsigned char secret[32];
+               unsigned char public[32];
+       } keys;
+};
+
+struct pakfire_key_signature {
+       unsigned char sig_algo[2];
+       pakfire_key_id key_id;
+       unsigned char signature[64];
 };
 
-int pakfire_key_create(struct pakfire_key** key, struct pakfire* pakfire, gpgme_key_t gpgkey) {
-       if (!gpgkey) {
+static int pakfire_key_create(struct pakfire_key** key, struct pakfire* pakfire,
+               const pakfire_key_algo_t algo, const pakfire_key_id id, EVP_PKEY* pkey) {
+       if (!pkey) {
                errno = EINVAL;
                return 1;
        }
@@ -57,16 +101,39 @@ int pakfire_key_create(struct pakfire_key** key, struct pakfire* pakfire, gpgme_
        k->pakfire = pakfire_ref(pakfire);
        k->nrefs = 1;
 
+       // Store the algorithm
+       switch (algo) {
+               case PAKFIRE_KEY_ALGO_ED25519:
+                       k->algo = algo;
+                       break;
+
+               default:
+                       ERROR(pakfire, "Unsupported key algorithm %d\n", algo);
+                       errno = ENOTSUP;
+                       goto ERROR;
+       }
+
+       // Store the key ID
+       memcpy(k->id, id, sizeof(k->id));
+
        // Keep a reference to this key
-       gpgme_key_ref(gpgkey);
-       k->gpgkey = gpgkey;
+       EVP_PKEY_up_ref(pkey);
+       k->pkey = pkey;
 
        *key = k;
        return 0;
+
+ERROR:
+       pakfire_key_unref(k);
+
+       return 1;
 }
 
 static void pakfire_key_free(struct pakfire_key* key) {
-       gpgme_key_unref(key->gpgkey);
+       // Free the key
+       if (key->pkey)
+               EVP_PKEY_free(key->pkey);
+
        pakfire_unref(key->pakfire);
        free(key);
 }
@@ -84,631 +151,709 @@ PAKFIRE_EXPORT void pakfire_key_unref(struct pakfire_key* key) {
        pakfire_key_free(key);
 }
 
-static int pakfire_find_key(struct pakfire_key** key, struct pakfire* pakfire, const char* fingerprint) {
-       if (!fingerprint) {
-               errno = EINVAL;
-               return 1;
-       }
-
-       // Reset key
-       *key = NULL;
+PAKFIRE_EXPORT const char* pakfire_key_get_algo(struct pakfire_key* key) {
+       switch (key->algo) {
+               case PAKFIRE_KEY_ALGO_ED25519:
+                       return "Ed255919";
 
-       // Fetch GPGME context
-       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pakfire);
-       if (!gpgctx)
-               return 1;
+               case PAKFIRE_KEY_ALGO_NULL:
+                       break;
+       }
 
-       DEBUG(pakfire, "Seaching for key with fingerprint %s\n", fingerprint);
+       return NULL;
+}
 
-       gpgme_key_t gpgkey = NULL;
+PAKFIRE_EXPORT int pakfire_key_generate(struct pakfire_key** key, struct pakfire* pakfire,
+               const pakfire_key_algo_t algo) {
+       EVP_PKEY* pkey = NULL;
+       EVP_PKEY_CTX* pctx = NULL;
+       pakfire_key_id key_id;
+       char error[ERROR_MAX];
+       int id;
        int r;
 
-       gpgme_error_t error = gpgme_get_key(gpgctx, fingerprint, &gpgkey, 0);
-       switch (gpg_error(error)) {
-               // Create a key object if we found something
-               case GPG_ERR_NO_ERROR:
-                       r = pakfire_key_create(key, pakfire, gpgkey);
-                       gpgme_key_unref(gpgkey);
-                       if (r)
-                               return r;
+       switch (algo) {
+               case PAKFIRE_KEY_ALGO_ED25519:
+                       id = EVP_PKEY_ED25519;
                        break;
 
-               // Nothing found
-               case GPG_ERR_EOF:
-                       break;
+               default:
+                       ERROR(pakfire, "Invalid key algorithm %d\n", algo);
+                       errno = EINVAL;
+                       return 1;
        }
 
-       return 0;
-}
+       // Generate a random key ID
+       r = RAND_bytes(key_id, sizeof(key_id));
+       if (r < 0) {
+               ERROR(pakfire, "Could not generate the key ID\n");
+               r = 1;
+               goto ERROR;
+       }
 
-PAKFIRE_EXPORT struct pakfire_key* pakfire_key_get(struct pakfire* pakfire, const char* fingerprint) {
-       struct pakfire_key* key = NULL;
+       // Setup the context
+       pctx = EVP_PKEY_CTX_new_id(id, NULL);
+       if (!pctx) {
+               ERROR(pakfire, "Could not allocate the OpenSSL context: %m\n");
+               r = 1;
+               goto ERROR;
+       }
 
-       int r = pakfire_find_key(&key, pakfire, fingerprint);
-       if (r)
-               return NULL;
+       // Prepare the context for key generation
+       r = EVP_PKEY_keygen_init(pctx);
+       if (r < 1) {
+               ERR_error_string_n(r, error, sizeof(error));
 
-       return key;
-}
+               ERROR(pakfire, "Could not prepare the context: %s\n", error);
+               r = 1;
+               goto ERROR;
+       }
 
-PAKFIRE_EXPORT int pakfire_key_delete(struct pakfire_key* key) {
-       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(key->pakfire);
+       // Generate the key
+       r = EVP_PKEY_keygen(pctx, &pkey);
+       if (r < 1) {
+               ERR_error_string_n(r, error, sizeof(error));
 
-       int r = 0;
-       gpgme_error_t error = gpgme_op_delete(gpgctx, key->gpgkey, 1);
-       if (error != GPG_ERR_NO_ERROR)
+               ERROR(pakfire, "Could not generate the key: %s\n", error);
                r = 1;
+               goto ERROR;
+       }
 
-       return r;
-}
+       // Create a key object
+       r = pakfire_key_create(key, pakfire, algo, key_id, pkey);
+       if (r)
+               goto ERROR;
 
-PAKFIRE_EXPORT const char* pakfire_key_get_fingerprint(struct pakfire_key* key) {
-       return key->gpgkey->fpr;
-}
+       // Success
+       r = 0;
 
-PAKFIRE_EXPORT const char* pakfire_key_get_uid(struct pakfire_key* key) {
-       if (key->gpgkey->uids)
-               return key->gpgkey->uids->uid;
+ERROR:
+       if (pctx)
+               EVP_PKEY_CTX_free(pctx);
+       if (pkey)
+               EVP_PKEY_free(pkey);
 
-       return NULL;
+       return r;
 }
 
-PAKFIRE_EXPORT const char* pakfire_key_get_name(struct pakfire_key* key) {
-       if (key->gpgkey->uids)
-               return key->gpgkey->uids->name;
+/*
+       Import
+*/
 
-       return NULL;
-}
-
-PAKFIRE_EXPORT const char* pakfire_key_get_email(struct pakfire_key* key) {
-       if (key->gpgkey->uids)
-               return key->gpgkey->uids->email;
+static int pakfire_key_import_secret_key(struct pakfire_key** key,
+               struct pakfire* pakfire, const struct pakfire_key_private_key* buffer) {
+       const pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_ED25519;
+       EVP_PKEY* pkey = NULL;
+       char error[ERROR_MAX];
+       int r;
 
-       return NULL;
-}
+       unsigned char checksum[64];
+       unsigned int length = sizeof(checksum);
 
-PAKFIRE_EXPORT const char* pakfire_key_get_pubkey_algo(struct pakfire_key* key) {
-       if (!key->gpgkey->subkeys)
-               return NULL;
+       // Check for input
+       if (!buffer) {
+               errno = EINVAL;
+               return 1;
+       }
 
-       switch (key->gpgkey->subkeys->pubkey_algo) {
-               case GPGME_PK_RSA:
-               case GPGME_PK_RSA_E:
-               case GPGME_PK_RSA_S:
-                       return "RSA";
+       // Check the signature algorithm
+       if (buffer->sig_algo[0] != 'E' || buffer->sig_algo[1] != 'd') {
+               ERROR(pakfire, "Unsupported signature algorithm\n");
+               errno = ENOTSUP;
+               r = 1;
+               goto ERROR;
+       }
 
-               case GPGME_PK_DSA:
-                       return "DSA";
+       // Check the KDF algorithm
+       if (buffer->kdf_algo[0] != 'B' || buffer->kdf_algo[1] != 'K') {
+               ERROR(pakfire, "Unsupported KDF algorithm\n");
+               errno = ENOTSUP;
+               r = 1;
+               goto ERROR;
+       }
 
-               case GPGME_PK_ECDSA:
-                       return "ECDSA";
+       // We don't support encrypted keys here
+       if (buffer->kdf_rounds) {
+               ERROR(pakfire, "Encrypted keys are not supported\n");
+               errno = ENOTSUP;
+               r = 1;
+               goto ERROR;
+       }
 
-               case GPGME_PK_ECDH:
-                       return "ECDH";
+       // Compute a SHA512 checksum over the key material
+       r = EVP_Digest(&buffer->keys, sizeof(buffer->keys), checksum, &length, EVP_sha512(), NULL);
+       if (r < 0) {
+               ERROR(pakfire, "Could not compute the checksum: %m\n");
+               r = 1;
+               goto ERROR;
+       }
 
-               case GPGME_PK_ECC:
-                       return "ECC";
+       // Compare the checksum
+       if (memcmp(buffer->checksum, checksum, sizeof(buffer->checksum)) != 0) {
+               ERROR(pakfire, "Checksum mismatch\n");
+               r = 1;
+               goto ERROR;
+       }
 
-               case GPGME_PK_EDDSA:
-                       return "EDDSA";
+       // Load the private key
+       pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL,
+               buffer->keys.secret, sizeof(buffer->keys.secret));
+       if (!pkey) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
 
-               case GPGME_PK_ELG:
-               case GPGME_PK_ELG_E:
-                       return "ELG";
+               ERROR(pakfire, "Could not load secret key: %s\n", error);
+               r = 1;
+               goto ERROR;
        }
 
-       return NULL;
-}
+       // Create a new key object
+       r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey);
+       if (r)
+               goto ERROR;
 
-PAKFIRE_EXPORT size_t pakfire_key_get_pubkey_length(struct pakfire_key* key) {
-       if (key->gpgkey->subkeys)
-               return key->gpgkey->subkeys->length;
+ERROR:
+       if (pkey)
+               EVP_PKEY_free(pkey);
 
        return 0;
 }
 
-PAKFIRE_EXPORT int pakfire_key_has_secret(struct pakfire_key* key) {
-       if (key->gpgkey)
-               return key->gpgkey->secret;
+static int pakfire_key_import_public_key(struct pakfire_key** key,
+               struct pakfire* pakfire, const struct pakfire_key_public_key* buffer) {
+       const pakfire_key_algo_t algo = PAKFIRE_KEY_ALGO_ED25519;
+       EVP_PKEY* pkey = NULL;
+       char error[ERROR_MAX];
+       int r;
 
-       return 0;
-}
+       // Check for input
+       if (!buffer) {
+               errno = EINVAL;
+               return 1;
+       }
 
-PAKFIRE_EXPORT time_t pakfire_key_get_created(struct pakfire_key* key) {
-       if (key->gpgkey->subkeys)
-               return key->gpgkey->subkeys->timestamp;
+       // Check the signature algorithm
+       if (buffer->sig_algo[0] != 'E' || buffer->sig_algo[1] != 'd') {
+               ERROR(pakfire, "Unsupported signature algorithm\n");
+               errno = ENOTSUP;
+               r = 1;
+               goto ERROR;
+       }
 
-       return 0;
-}
+       // Load the public key
+       pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL,
+               buffer->pubkey, sizeof(buffer->pubkey));
+       if (!pkey) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
 
-PAKFIRE_EXPORT time_t pakfire_key_get_expires(struct pakfire_key* key) {
-       if (key->gpgkey->subkeys)
-               return key->gpgkey->subkeys->expires;
+               ERROR(pakfire, "Could not load public key: %s\n", error);
+               r = 1;
+               goto ERROR;
+       }
 
-       return 0;
-}
+       // Create a new key object
+       r = pakfire_key_create(key, pakfire, algo, buffer->id, pkey);
+       if (r)
+               goto ERROR;
 
-PAKFIRE_EXPORT int pakfire_key_is_revoked(struct pakfire_key* key) {
-       if (key->gpgkey->subkeys)
-               return key->gpgkey->subkeys->revoked;
+ERROR:
+       if (pkey)
+               EVP_PKEY_free(pkey);
 
-       return 0;
+       return r;
 }
 
-static int pakfire_key_write_to_keystore(struct pakfire_key* key) {
-       // Fetch keystore path
-       const char* keystore_path = pakfire_get_keystore_path(key->pakfire);
-       if (!keystore_path)
-               return 1;
-
-       // Fetch fingerprint
-       const char* fpr = pakfire_key_get_fingerprint(key);
-       if (!fpr)
-               return 1;
+PAKFIRE_EXPORT int pakfire_key_import(struct pakfire_key** key,
+               struct pakfire* pakfire, FILE* f) {
+       BIO* bio = NULL;
+       BIO* b64 = NULL;
+       char buffer[4096];
+       size_t bytes_read = 0;
+       int r;
 
-       char path[PATH_MAX];
+       // Setup the base64 decoder
+       b64 = BIO_new(BIO_f_base64());
+       if (!b64) {
+               ERROR(pakfire, "Could not setup the base64 decoder\n");
+               r = 1;
+               goto ERROR;
+       }
 
-       // Make path
-       int r = pakfire_string_format(path, "%s/%s.key", keystore_path, fpr);
-       if (r)
-               return r;
+       bio = BIO_new_fp(f, BIO_NOCLOSE);
+       if (!bio) {
+               ERROR(pakfire, "Could not open BIO\n");
+               r = 1;
+               goto ERROR;
+       }
 
-       // Create parent directory
-       r = pakfire_mkparentdir(path, 0700);
-       if (r)
-               return r;
+       BIO_push(b64, bio);
 
-       // Create file
-       FILE* f = fopen(path, "w");
-       if (!f) {
-               ERROR(key->pakfire, "Could not open %s for writing: %m\n", path);
-               return 1;
+       // Try to read everything into the buffer
+       r = BIO_read_ex(b64, buffer, sizeof(buffer), &bytes_read);
+       if (r < 0) {
+               ERROR(pakfire, "Could not read data\n");
+               r = 1;
+               goto ERROR;
        }
 
-       // Make files with secret keys non-world-readable
-       if (pakfire_key_has_secret(key)) {
-               r = chmod(path, 0600);
-               if (r) {
-                       ERROR(key->pakfire, "Could not chmod %s: %m\n", path);
-                       fclose(f);
-                       return r;
-               }
-       }
+       const struct pakfire_key_private_key* private_key =
+               (const struct pakfire_key_private_key*)buffer;
+       const struct pakfire_key_public_key* public_key =
+               (const struct pakfire_key_public_key*)buffer;
 
-       // Write key to file
-       r = pakfire_key_export(key, f, 0);
-       if (r) {
-               ERROR(key->pakfire, "Could not export key %s: %m\n", fpr);
-               unlink(path);
+       // Try to find what we have read
+       switch (bytes_read) {
+
+               // Import a private key
+               case sizeof(*private_key):
+                       r = pakfire_key_import_secret_key(key, pakfire, private_key);
+                       break;
+
+               // Import a public key
+               case sizeof(*public_key):
+                       r = pakfire_key_import_public_key(key, pakfire, public_key);
+                       break;
+
+               default:
+                       ERROR(pakfire, "Unsupported key type\n");
+                       r = 1;
+                       goto ERROR;
        }
 
-       // Close file
-       fclose(f);
+ERROR:
+       if (b64)
+               BIO_free(b64);
+       if (bio)
+               BIO_free(bio);
 
        return r;
 }
 
-PAKFIRE_EXPORT int pakfire_key_generate(struct pakfire_key** key, struct pakfire* pakfire,
-               const char* algo, const char* userid) {
+int pakfire_key_import_from_string(struct pakfire_key** key,
+               struct pakfire* pakfire, const char* data, const size_t length) {
+       FILE* f = NULL;
        int r;
 
-       // Check input
-       if (!algo || !userid) {
-               errno = EINVAL;
-               return 1;
+       // Map the data to a file
+       f = fmemopen((char*)data, length, "r");
+       if (!f) {
+               ERROR(pakfire, "Could not map the key to file: %m\n");
+               r = 1;
+               goto ERROR;
        }
 
-       // Fetch GPGME context
-       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pakfire);
-       if (!gpgctx)
-               return 1;
+       // Import the key
+       r = pakfire_key_import(key, pakfire, f);
 
-       const unsigned int flags =
-               // Key should be able to be used to sign
-               GPGME_CREATE_SIGN |
-               // Don't set a password
-               GPGME_CREATE_NOPASSWD |
-               // The key should never expire
-               GPGME_CREATE_NOEXPIRE;
+ERROR:
+       if (f)
+               fclose(f);
 
-       // Generate the key
-       gpgme_error_t error = gpgme_op_createkey(gpgctx, userid,
-               algo, 0, 0, NULL, flags);
-
-       if (error != GPG_ERR_NO_ERROR) {
-               switch (gpg_err_code(error)) {
-                       case GPG_ERR_USER_ID_EXISTS:
-                       case GPG_ERR_NAME_EXISTS:
-                               errno = EINVAL;
-                               break;
-
-                       default:
-                               break;
-               }
+       return r;
+}
+
+static int pakfire_key_get_public_key(struct pakfire_key* key,
+               unsigned char* buffer, const size_t length) {
+       char error[ERROR_MAX];
+       int r;
 
-               ERROR(pakfire, "%s\n", gpgme_strerror(error));
+       size_t l = length;
+
+       // Extract the raw public key
+       r = EVP_PKEY_get_raw_public_key(key->pkey, buffer, &l);
+       if (r < 0) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
+
+               ERROR(key->pakfire, "Could not extract the public key: %s\n", error);
                return 1;
        }
 
-       // Retrieve the result
-       gpgme_genkey_result_t result = gpgme_op_genkey_result(gpgctx);
-
-       // Retrieve the key by its fingerprint
-       r = pakfire_find_key(key, pakfire, result->fpr);
-       if (r)
-               return r;
+       if (l > length) {
+               ERROR(key->pakfire, "The buffer was too small to write the public key\n");
+               errno = ENOBUFS;
+               return 1;
+       }
 
-       // Store the key in the keystore
-       return pakfire_key_write_to_keystore(*key);
+       return 0;
 }
 
-static int pakfire_key_data(struct pakfire_key* key, char** buffer, size_t* length,
-               const pakfire_key_export_mode_t mode) {
-       char* output = NULL;
+static int pakfire_key_get_secret_key(struct pakfire_key* key,
+               unsigned char* buffer, const size_t length) {
+       char error[ERROR_MAX];
+       int r;
 
-       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(key->pakfire);
-       if (!gpgctx)
-               return 1;
+       size_t l = length;
 
-       gpgme_export_mode_t gpgmode = 0;
-       switch (mode) {
-               case PAKFIRE_KEY_EXPORT_MODE_SECRET:
-                       gpgmode |= GPGME_EXPORT_MODE_SECRET;
-                       break;
+       // Extract the raw secret key
+       r = EVP_PKEY_get_raw_private_key(key->pkey, buffer, &l);
+       if (r < 0) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
 
-               default:
-                       break;
+               ERROR(key->pakfire, "Could not extract the secret key: %s\n", error);
+               return 1;
        }
 
-       const char* fingerprint = pakfire_key_get_fingerprint(key);
-
-       DEBUG(key->pakfire, "Exporting key %s\n", fingerprint);
+       if (l > length) {
+               ERROR(key->pakfire, "The buffer was too small to write the secret key\n");
+               errno = ENOBUFS;
+               return 1;
+       }
 
-       gpgme_data_t data = NULL;
-       int r = 1;
+       return 0;
+}
 
-       // Initialize the buffer
-       gpgme_error_t e = gpgme_data_new(&data);
-       if (gpg_err_code(e) != GPG_ERR_NO_ERROR)
-               goto ERROR;
+/*
+       Export
+*/
 
-       // Encode output as ASCII
-       e = gpgme_data_set_encoding(data, GPGME_DATA_ENCODING_ARMOR);
-       if (gpg_err_code(e) != GPG_ERR_NO_ERROR)
-               goto ERROR;
+static int pakfire_key_export_private_key(struct pakfire_key* key,
+               struct pakfire_key_private_key* buffer) {
+       unsigned char checksum[64];
+       unsigned int length = sizeof(checksum);
+       int r;
 
-       // Copy the key to the buffer
-       e = gpgme_op_export(gpgctx, fingerprint, gpgmode, data);
-       if (gpg_err_code(e) != GPG_ERR_NO_ERROR)
-               goto ERROR;
+       // Write the algorithm
+       switch (key->algo) {
+               case PAKFIRE_KEY_ALGO_ED25519:
+                       // Signature Algortihm
+                       buffer->sig_algo[0] = 'E';
+                       buffer->sig_algo[1] = 'd';
 
-       // Fetch data from buffer
-       output = gpgme_data_release_and_get_mem(data, length);
+                       // KDF Algorithm
+                       buffer->kdf_algo[0] = 'B';
+                       buffer->kdf_algo[1] = 'K';
+                       break;
 
-       // Reset data so it won't be freed again
-       data = NULL;
+               default:
+                       ERROR(key->pakfire, "Unknown algorithm\n");
+                       return 1;
+       }
 
-       // Allocate buffer
-       *buffer = malloc(*length);
-       if (!*buffer) {
-               r = 1;
-               goto ERROR;
+       // Generate a salt
+       r = RAND_bytes(buffer->kdf_salt, sizeof(buffer->kdf_salt));
+       if (r < 1) {
+               ERROR(key->pakfire, "Could not generate salt\n");
+               return 1;
        }
 
-       // Copy the output buffer
-       memcpy(*buffer, output, *length);
+       // Copy the key ID
+       memcpy(buffer->id, key->id, sizeof(buffer->id));
 
-       // Success
-       r = 0;
+       // Write the public key
+       r = pakfire_key_get_public_key(key, buffer->keys.public, sizeof(buffer->keys.public));
+       if (r) {
+               ERROR(key->pakfire, "Could not export the public key: %m\n");
+               return r;
+       }
 
-ERROR:
-       if (output)
-               gpgme_free(output);
-       if (data)
-               gpgme_data_release(data);
+       // Write the secret key
+       r = pakfire_key_get_secret_key(key, buffer->keys.secret, sizeof(buffer->keys.secret));
+       if (r) {
+               ERROR(key->pakfire, "Could not export the secret key: %m\n");
+               return r;
+       }
 
-       return r;
-}
+       // Compute a SHA512 checksum over the key material
+       r = EVP_Digest(&buffer->keys, sizeof(buffer->keys), checksum, &length, EVP_sha512(), NULL);
+       if (r < 0) {
+               ERROR(key->pakfire, "Could not compute the checksum: %m\n");
+               return 1;
+       }
 
-PAKFIRE_EXPORT int pakfire_key_get_public_key(struct pakfire_key* key,
-               char** buffer, size_t* length) {
-       // Fetch the public key
-       return pakfire_key_data(key, buffer, length, PAKFIRE_KEY_EXPORT_MODE_PUBLIC);
-}
+       // Copy the first couple of bytes of the checksum
+       memcpy(buffer->checksum, checksum, sizeof(buffer->checksum));
 
-PAKFIRE_EXPORT int pakfire_key_get_secret_key(struct pakfire_key* key,
-               char** buffer, size_t* length) {
-       // Fetch the secret key
-       return pakfire_key_data(key, buffer, length, PAKFIRE_KEY_EXPORT_MODE_SECRET);
+       // Success!
+       return 0;
 }
 
-PAKFIRE_EXPORT int pakfire_key_export(struct pakfire_key* key, FILE* f,
-               pakfire_key_export_mode_t mode) {
-       char* buffer = NULL;
-       size_t length = 0;
+static int pakfire_key_export_public_key(struct pakfire_key* key,
+               struct pakfire_key_public_key* buffer) {
        int r;
 
-       // Check input
-       if (!f) {
-               errno = EINVAL;
-               return 1;
-       }
-
-       r = pakfire_key_data(key, &buffer, &length, mode);
-       if (r)
-               return r;
+       // Write the algorithm
+       switch (key->algo) {
+               case PAKFIRE_KEY_ALGO_ED25519:
+                       buffer->sig_algo[0] = 'E';
+                       buffer->sig_algo[1] = 'd';
+                       break;
 
-       // Write key to file
-       size_t bytes_written = fwrite(buffer, 1, length, f);
-       if (bytes_written < length) {
-               r = 1;
-               goto ERROR;
+               default:
+                       ERROR(key->pakfire, "Unknown algorithm\n");
+                       return 1;
        }
 
-       // Flush f
-       r = fflush(f);
-       if (r)
-               goto ERROR;
-
-       // Success
-       r = 0;
+       // Copy the key ID
+       memcpy(buffer->id, key->id, sizeof(buffer->id));
 
-ERROR:
-       if (buffer)
-               gpgme_free(buffer);
+       // Write the public key
+       r = pakfire_key_get_public_key(key, buffer->pubkey, sizeof(buffer->pubkey));
+       if (r) {
+               ERROR(key->pakfire, "Could not export the public key: %m\n");
+               return r;
+       }
 
-       return r;
+       // Success!
+       return 0;
 }
 
-PAKFIRE_EXPORT int pakfire_key_import(struct pakfire* pakfire, FILE* f,
-               struct pakfire_key*** keys) {
-       gpgme_data_t data;
-       int r = 1;
-
-       if (!f) {
-               errno = EINVAL;
-               return 1;
-       }
+PAKFIRE_EXPORT int pakfire_key_export(struct pakfire_key* key, FILE* f,
+               const pakfire_key_export_mode_t mode) {
+       struct pakfire_key_public_key public_key = { 0 };
+       struct pakfire_key_private_key private_key = { 0 };
+       int r;
 
-       // Reset keys
-       if (keys)
-               *keys = NULL;
+       BIO* bio = NULL;
+       BIO* b64 = NULL;
 
-       // Fetch GPGME context
-       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pakfire);
-       if (!gpgctx)
-               return 1;
+       // Setup the base64 encoder
+       b64 = BIO_new(BIO_f_base64());
+       if (!b64) {
+               ERROR(key->pakfire, "Could not setup the base64 encoder\n");
+               r = 1;
+               goto ERROR;
+       }
 
-       gpgme_import_result_t result = NULL;
+       // Disable line breaks and a trailing newline
+       BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
 
-       // Import key data
-       gpgme_error_t e = gpgme_data_new_from_stream(&data, f);
-       if (gpg_error(e) != GPG_ERR_NO_ERROR)
+       bio = BIO_new_fp(f, BIO_NOCLOSE);
+       if (!bio) {
+               ERROR(key->pakfire, "Could not open BIO\n");
+               r = 1;
                goto ERROR;
+       }
 
-       // Try importing the key(s)
-       e = gpgme_op_import(gpgctx, data);
-
-       switch (gpg_error(e)) {
-               // Everything went fine
-               case GPG_ERR_NO_ERROR:
-                       result = gpgme_op_import_result(gpgctx);
+       BIO_push(b64, bio);
 
-                       // Keep the result
-                       gpgme_result_ref(result);
+       switch (mode) {
+               case PAKFIRE_KEY_EXPORT_MODE_PUBLIC:
+                       r = pakfire_key_export_public_key(key, &public_key);
+                       if (r)
+                               goto ERROR;
 
-                       // Did we import any keys?
-                       gpgme_import_status_t status = result->imports;
-                       if (!status) {
-                               errno = ENOENT;
+                       // Write the output
+                       r = BIO_write(b64, &public_key, sizeof(public_key));
+                       if (r < 0) {
+                               ERROR(key->pakfire, "Could not write the public key\n");
+                               r = 1;
                                goto ERROR;
                        }
+                       break;
 
-                       DEBUG(pakfire, "Keys considered   = %d\n", result->considered);
-                       DEBUG(pakfire, "Keys imported     = %d\n", result->imported);
-                       DEBUG(pakfire, "Keys not imported = %d\n", result->not_imported);
-
-                       if (keys) {
-                               // Allocate array
-                               *keys = calloc(result->imported + 1, sizeof(**keys));
-                               if (!*keys)
-                                       goto ERROR;
-
-                               struct pakfire_key* key = NULL;
-
-                               // Retrieve all imported keys
-                               for (int i = 0; i < result->imported && status; i++, status = status->next) {
-                                       DEBUG(pakfire, "Imported key %s - %s\n",
-                                               status->fpr, gpgme_strerror(status->result));
-
-                                       // Fetch the key by its fingerprint
-                                       r = pakfire_find_key(&key, pakfire, status->fpr);
-                                       if (r)
-                                               goto ERROR;
-
-                                       // Append to array
-                                       (*keys)[i] = key;
+               case PAKFIRE_KEY_EXPORT_MODE_PRIVATE:
+                       r = pakfire_key_export_private_key(key, &private_key);
+                       if (r)
+                               goto ERROR;
 
-                                       // Write key to keystore
-                                       r = pakfire_key_write_to_keystore(key);
-                                       if (r)
-                                               goto ERROR;
-                               }
+                       // Write the output
+                       r = BIO_write(b64, &private_key, sizeof(private_key));
+                       if (r < 0) {
+                               ERROR(key->pakfire, "Could not write the private key\n");
+                               r = 1;
+                               goto ERROR;
                        }
                        break;
 
-               // Input was invalid
-               case GPG_ERR_INV_VALUE:
-                       errno = EINVAL;
-                       break;
-
-               // Fall through for any other errors
                default:
-                       ERROR(pakfire, "Failed with gpgme error: %s\n", gpgme_strerror(e));
-                       break;
+                       errno = EINVAL;
+                       r = 1;
+                       goto ERROR;
        }
 
-       // Success
-       r = 0;
+       // Flush all buffers
+       BIO_flush(b64);
 
-ERROR:
-       if (result)
-               gpgme_result_unref(result);
-       gpgme_data_release(data);
+       // Append a trailing newline
+       fprintf(f, "\n");
 
-       // Free keys on error
-       if (r && keys && *keys) {
-               for (struct pakfire_key** key = *keys; *key; key++)
-                       pakfire_key_unref(*key);
-               free(*keys);
+       // Success!
+       r = 0;
 
-               *keys = NULL;
-       }
+ERROR:
+       if (b64)
+               BIO_free(b64);
+       if (bio)
+               BIO_free(bio);
 
        return r;
 }
 
 PAKFIRE_EXPORT char* pakfire_key_dump(struct pakfire_key* key) {
-       char date[1024];
-       char* s = NULL;
+       char* buffer = NULL;
+       FILE* f = NULL;
+       int fd = -1;
        int r;
 
-       time_t created = pakfire_key_get_created(key);
-
-       // Format creation time
-       r = pakfire_strftime(date, "%Y-%m-%d", created);
-       if (r)
+       // Allocate a buffer in memory
+       fd = memfd_create("pakfire-key-dump", MFD_CLOEXEC);
+       if (fd < 0) {
+               ERROR(key->pakfire, "Could not allocate a temporary file: %m\n");
+               r = 1;
                goto ERROR;
+       }
 
-       asprintf(&s, "pub %s%zu/%s %s",
-               pakfire_key_get_pubkey_algo(key),
-               pakfire_key_get_pubkey_length(key),
-               pakfire_key_get_fingerprint(key),
-               date
-       );
+       // Re-open as FILE handle
+       f = fdopen(fd, "r+");
+       if (!f) {
+               ERROR(key->pakfire, "Could not open file handle for temporary file: %m\n");
+               r = 1;
+               goto ERROR;
+       }
 
-       const char* uid = pakfire_key_get_uid(key);
-       if (uid) {
-               asprintf(&s, "%s\n    %s", s, uid);
+       // Export the public part of the key
+       r = pakfire_key_export(key, f, PAKFIRE_KEY_EXPORT_MODE_PUBLIC);
+       if (r) {
+               ERROR(key->pakfire, "Could not export key: %m\n");
+               goto ERROR;
        }
 
-       time_t expires = pakfire_key_get_expires(key);
-       if (expires) {
-               r = pakfire_strftime(date, "%Y-%m-%d", expires);
-               if (r)
-                       goto ERROR;
+       // Determine the length of the buffer
+       size_t length = ftell(f);
+
+       // Go back to the beginning of the file
+       rewind(f);
 
-               asprintf(&s, "%s\n    %s: %s", s, _("Expires"), date);
+       // Allocate a buffer
+       buffer = calloc(1, length + 1);
+       if (!buffer) {
+               ERROR(key->pakfire, "Could not allocate buffer of %zu byte(s)\n", length + 1);
+               r = 1;
+               goto ERROR;
        }
 
-       return s;
+       // Read everything into the buffer
+       size_t bytes_read = fread(buffer, 1, length, f);
+       if (bytes_read < length) {
+               ERROR(key->pakfire, "Could not read back the buffer: %m\n");
+               r = 1;
+               goto ERROR;
+       }
+
+       // Success!
+       r = 0;
 
 ERROR:
-       if (s)
-               free(s);
+       if (f)
+               fclose(f);
+       if (fd >= 0)
+               close(fd);
+
+       // Free the buffer on error
+       if (r && buffer) {
+               free(buffer);
+               buffer = NULL;
+       }
 
-       return NULL;
+       return buffer;
 }
 
-int pakfire_key_sign(struct pakfire_key* key, const char* buffer, const size_t buffer_length,
-               char** signature, size_t* signature_length, time_t* timestamp) {
-       // Fetch GPGME context
-       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(key->pakfire);
-       if (!gpgctx)
+/*
+       Sign
+*/
+
+static int __pakfire_key_sign(struct pakfire_key* key,
+               struct pakfire_key_signature* signature, const void* data, const size_t length) {
+       EVP_PKEY_CTX* pctx = NULL;
+       EVP_MD_CTX* mdctx = NULL;
+       char error[ERROR_MAX];
+       int r;
+
+       // Check inputs
+       if (!signature || !data || !length) {
+               errno = EINVAL;
                return 1;
+       }
 
-       // Remove any previous signers
-       gpgme_signers_clear(gpgctx);
+       // Set algorithm
+       signature->sig_algo[0] = 'E';
+       signature->sig_algo[1] = 'd';
 
-       gpgme_data_t data = NULL;
-       gpgme_data_t sign = NULL;
-       gpgme_error_t e;
-       char* __signature = NULL;
-       int r = 1;
+       // Set the key ID
+       memcpy(signature->key_id, key->id, sizeof(signature->key_id));
 
-       // Enable the key
-       e = gpgme_signers_add(gpgctx, key->gpgkey);
-       if (gpgme_err_code(e)) {
-               ERROR(key->pakfire, "Could not select key for signing: %s\n",
-                       gpgme_strerror(e));
+       // Create a signing context
+       pctx = EVP_PKEY_CTX_new(key->pkey, NULL);
+       if (!pctx) {
+               ERROR(key->pakfire, "Could not initialize the signing context: %m\n");
+               r = 1;
                goto ERROR;
        }
 
-       // Initialize data buffer
-       e = gpgme_data_new_from_mem(&data, buffer, buffer_length, 0);
-       if (gpgme_err_code(e)) {
-               ERROR(key->pakfire, "Could not initialize data buffer: %s\n",
-                       gpgme_strerror(e));
+       // Create a message digest context
+       mdctx = EVP_MD_CTX_new();
+       if (!mdctx) {
+               ERROR(key->pakfire, "Could not initialize the message digest context: %m\n");
+               r = 1;
                goto ERROR;
        }
 
-       // Initialize signature buffer
-       e = gpgme_data_new(&sign);
-       if (gpgme_err_code(e)) {
-               ERROR(key->pakfire, "Could not initialize signature buffer: %s\n",
-                       gpgme_strerror(e));
+       // Connect the two contexts
+       EVP_MD_CTX_set_pkey_ctx(mdctx, pctx);
+
+       size_t signature_length = sizeof(signature->signature);
+
+       // Create a signature over the digest
+       r = EVP_DigestSign(mdctx, signature->signature, &signature_length, data, length);
+       if (r < 1) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
+
+               ERROR(key->pakfire, "Could not sign content: %s\n", error);
+               r = 1;
                goto ERROR;
        }
 
-       // Create the signature
-       e = gpgme_op_sign(gpgctx, data, sign, GPGME_SIG_MODE_DETACH);
-       switch (gpgme_err_code(e)) {
-               // Everything went OK
-               case GPG_ERR_NO_ERROR:
-                       break;
+       // Success!
+       r = 0;
 
-               default:
-                       ERROR(key->pakfire, "Could not sign: %s\n", gpgme_strerror(e));
+ERROR:
+       if (pctx)
+               EVP_PKEY_CTX_free(pctx);
+       if (mdctx)
+               EVP_MD_CTX_free(mdctx);
 
-                       // Set errno to something useful
-                       errno = gpgme_err_code_to_errno(e);
-                       goto ERROR;
-       }
+       return r;
+}
 
-       // Print some status details
-       gpgme_sign_result_t result = gpgme_op_sign_result(gpgctx);
-       if (result) {
-               for (gpgme_new_signature_t s = result->signatures; s; s = s->next) {
-                       DEBUG(key->pakfire, "Signature created\n");
-                       DEBUG(key->pakfire, "  Key       : %s\n", s->fpr);
-                       DEBUG(key->pakfire, "  Algorithm : %s\n", gpgme_pubkey_algo_name(s->pubkey_algo));
-                       DEBUG(key->pakfire, "  Hash      : %s\n", gpgme_hash_algo_name(s->hash_algo));
-                       DEBUG(key->pakfire, "  Timestamp : %ld\n", s->timestamp);
+int pakfire_key_sign(struct pakfire_key* key,
+               FILE* f, const char* data, const size_t length, const char* comment) {
+       struct pakfire_key_signature signature = { 0 };
+       char* s = NULL;
+       int r;
+
+       // Create a signature
+       r = __pakfire_key_sign(key, &signature, data, length);
+       if (r)
+               return r;
 
-                       // Store timestamp
-                       if (timestamp)
-                               *timestamp = s->timestamp;
+       // Write the comment
+       if (comment) {
+               r = fprintf(f, "untrusted comment: %s\n", comment);
+               if (r < 0) {
+                       ERROR(key->pakfire, "Could not write comment: %m\n");
+                       r = 1;
+                       goto ERROR;
                }
        }
 
-       // Extract the signature
-       __signature = gpgme_data_release_and_get_mem(sign, signature_length);
-       if (!__signature) {
-               ERROR(key->pakfire, "The signature was unexpectedly empty: %m\n");
+       // Encode the signature to base64
+       r = pakfire_b64encode(key->pakfire, &s, &signature, sizeof(signature));
+       if (r)
                goto ERROR;
-       }
 
-       // Sign is now released and we should not do this again below
-       sign = NULL;
-
-       // Because GPGME could be using its internal allocator, we need to copy the signature
-       // and release the memory that we got from GPGME using gpgme_free().
-       *signature = malloc(*signature_length);
-       if (!*signature)
+       // Write the signature
+       r = fprintf(f, "%s\n", s);
+       if (r < 0) {
+               ERROR(key->pakfire, "Could not write the signature: %m\n");
+               r = 1;
                goto ERROR;
+       }
 
-       memcpy(*signature, __signature, *signature_length);
-
-       // Success
+       // Success!
        r = 0;
 
 ERROR:
-       if (__signature)
-               gpgme_free(__signature);
-       if (data)
-               gpgme_data_release(data);
-       if (sign)
-               gpgme_data_release(sign);
+       if (s)
+               free(s);
 
        return r;
 }
index bb55e2fa256c50bfd8c3471c099a6cc87fffd5e4..4343ac39cb8367587c247982c0495e008fcb2281 100644 (file)
@@ -85,8 +85,10 @@ static int pakfire_keystore_import(struct pakfire* pakfire, gpgme_ctx_t ctx) {
                                continue;
                        }
 
+#if 0
                        // Import keys from file
                        r = pakfire_key_import(pakfire, f, NULL);
+#endif
                        fclose(f);
 
                        // End if key import was unsuccessful
index c5f99922d60fd20c9d2d6db9991bc8fcf1ec0ca1..57931cf72d2ab49f143c91cb22cdeeda471010e5 100644 (file)
@@ -32,7 +32,6 @@ global:
        pakfire_get_repo;
        pakfire_get_repos;
        pakfire_install;
-       pakfire_list_keys;
        pakfire_ref;
        pakfire_refresh;
        pakfire_search;
@@ -133,19 +132,9 @@ global:
        pakfire_key_export;
        pakfire_key_generate;
        pakfire_key_get;
-       pakfire_key_get_created;
-       pakfire_key_get_email;
-       pakfire_key_get_expires;
-       pakfire_key_get_fingerprint;
-       pakfire_key_get_name;
-       pakfire_key_get_pubkey_algo;
-       pakfire_key_get_pubkey_length;
-       pakfire_key_get_public_key;
-       pakfire_key_get_secret_key;
-       pakfire_key_get_uid;
-       pakfire_key_has_secret;
+       pakfire_key_get_algo;
+       pakfire_key_get_id;
        pakfire_key_import;
-       pakfire_key_is_revoked;
        pakfire_key_ref;
        pakfire_key_unref;
 
index 4f28310a6697d517cb4dcd2cee636dcf20d4c2bc..5094bb3601c90f48bbf65d9d40e1b1262ab8384c 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <archive.h>
 #include <archive_entry.h>
-#include <gpgme.h>
 #include <magic.h>
 #include <solv/evr.h>
 #include <solv/pool.h>
@@ -48,7 +47,6 @@
 #include <pakfire/constants.h>
 #include <pakfire/db.h>
 #include <pakfire/dependencies.h>
-#include <pakfire/keystore.h>
 #include <pakfire/logging.h>
 #include <pakfire/mount.h>
 #include <pakfire/package.h>
@@ -64,7 +62,6 @@
 #include <pakfire/ui.h>
 #include <pakfire/util.h>
 
-#define KEYSTORE_DIR "/etc/pakfire/trusted.keys.d"
 #define LOCK_PATH PAKFIRE_PRIVATE_DIR "/.lock"
 
 struct pakfire {
@@ -74,7 +71,6 @@ struct pakfire {
        char lock_path[PATH_MAX];
        char cache_path[PATH_MAX];
        char arch[ARCH_MAX];
-       char keystore_path[PATH_MAX];
 
        int flags;
 
@@ -126,9 +122,6 @@ struct pakfire {
                char tag[40];
        } distro;
 
-       // GPG Context
-       gpgme_ctx_t gpgctx;
-
        // Magic Context
        magic_t magic;
 
@@ -406,10 +399,6 @@ static void pakfire_free(struct pakfire* pakfire) {
        if (pakfire->magic)
                magic_close(pakfire->magic);
 
-       // Release GPGME context
-       if (pakfire->gpgctx)
-               pakfire_keystore_destroy(pakfire, &pakfire->gpgctx);
-
        // Release lock (if not already done so)
        pakfire_release_lock(pakfire);
 
@@ -959,13 +948,6 @@ PAKFIRE_EXPORT int pakfire_create(struct pakfire** pakfire, const char* path,
                goto ERROR;
        }
 
-       // Set keystore path
-       r = pakfire_path(p, p->keystore_path, "%s", KEYSTORE_DIR);
-       if (r) {
-               ERROR(p, "Could not set keystore path: %m\n");
-               goto ERROR;
-       }
-
        // Make path for private files
        r = pakfire_path(p, private_dir, "%s", PAKFIRE_PRIVATE_DIR);
        if (r)
@@ -978,11 +960,6 @@ PAKFIRE_EXPORT int pakfire_create(struct pakfire** pakfire, const char* path,
                goto ERROR;
        }
 
-       // Initialize keystore
-       r = pakfire_keystore_init(p, &p->gpgctx);
-       if (r)
-               goto ERROR;
-
        // Populate pool
        r = pakfire_populate_pool(p);
        if (r)
@@ -1088,10 +1065,6 @@ void pakfire_release_lock(struct pakfire* pakfire) {
        unlink(pakfire->lock_path);
 }
 
-const char* pakfire_get_keystore_path(struct pakfire* pakfire) {
-       return pakfire->keystore_path;
-}
-
 int __pakfire_path(struct pakfire* pakfire, char* path, const size_t length,
                const char* format, ...) {
        char buffer[PATH_MAX];
@@ -1134,10 +1107,6 @@ int __pakfire_cache_path(struct pakfire* pakfire, char* path, size_t length,
        return __pakfire_path_join(path, length, pakfire->cache_path, buffer);
 }
 
-gpgme_ctx_t pakfire_get_gpgctx(struct pakfire* pakfire) {
-       return pakfire->gpgctx;
-}
-
 magic_t pakfire_get_magic(struct pakfire* pakfire) {
        int r;
 
@@ -1171,64 +1140,6 @@ ERROR:
        return NULL;
 }
 
-PAKFIRE_EXPORT int pakfire_list_keys(struct pakfire* pakfire, struct pakfire_key*** keys) {
-       // Reset keys
-       *keys = NULL;
-
-       // Fetch GPGME context
-       gpgme_ctx_t gpgctx = pakfire_get_gpgctx(pakfire);
-       if (!gpgctx)
-               return 1;
-
-       struct pakfire_key* key = NULL;
-       gpgme_key_t gpgkey = NULL;
-       size_t length = 0;
-       int r = 1;
-
-       // Iterate over all keys and import them to the list
-       gpgme_error_t e = gpgme_op_keylist_start(gpgctx, NULL, 0);
-       if (e)
-               goto ERROR;
-
-       while (!e) {
-               e = gpgme_op_keylist_next(gpgctx, &gpgkey);
-               if (e)
-                       break;
-
-               // Create key
-               r = pakfire_key_create(&key, pakfire, gpgkey);
-               gpgme_key_unref(gpgkey);
-               if (r)
-                       goto ERROR;
-
-               // Append to keys
-               *keys = reallocarray(*keys, length + 2, sizeof(**keys));
-               if (!*keys) {
-                       r = 1;
-                       goto ERROR;
-               }
-
-               // Store key in array
-               (*keys)[length++] = key;
-
-               // Terminate the array
-               (*keys)[length] = NULL;
-       }
-
-       // Done
-       return 0;
-
-ERROR:
-       if (*keys) {
-               for (struct pakfire_key** _key = *keys; *_key; _key++)
-                       pakfire_key_unref(*_key);
-               free(*keys);
-               keys = NULL;
-       }
-
-       return r;
-}
-
 int pakfire_repo_walk(struct pakfire* pakfire,
                pakfire_repo_walk_callback callback, void* p) {
        struct pakfire_repo* repo = NULL;
index a61e207dde9935d8ad836d0ae94d98d35013262b..600d9d080abebb24d36b23b13885744f34b28247 100644 (file)
@@ -58,8 +58,8 @@ struct pakfire_repo_appdata {
        char* description;
        char* baseurl;
 
-       // Key fingerprint
-       char key[PAKFIRE_KEY_FPR_MAXLEN];
+       // Key
+       char* key;
 
        // Mirrorlist
        char* mirrorlist_url;
@@ -77,6 +77,8 @@ struct pakfire_repo {
        struct pakfire_repo_appdata* appdata;
 
        struct pakfire_mirrorlist* mirrorlist;
+
+       struct pakfire_key* key;
 };
 
 int pakfire_repo_is_internal(struct pakfire_repo* repo) {
@@ -165,46 +167,35 @@ static int pakfire_repo_retrieve(
        return r;
 }
 
-static int pakfire_repo_import_key(struct pakfire_repo* repo, FILE* f) {
-       struct pakfire_key** keys = NULL;
+static int pakfire_repo_import_key(struct pakfire_repo* repo, const char* data) {
+       struct pakfire_key* key = NULL;
        int r;
 
-       // Import any keys from the file descriptor
-       r = pakfire_key_import(repo->pakfire, f, &keys);
-       if (r)
-               return r;
-
-       /*
-               XXX It can happen, that more than one repository are using the same
-               key which can only be imported once. The second time, the key won't
-               be returned which lets us end up with that repository having no key.
-       */
-
-       for (struct pakfire_key** key = keys; *key; key++) {
-               char* dump = pakfire_key_dump(*key);
-
-               if (dump)
-                       DEBUG(repo->pakfire, "Imported key:\n%s\n", dump);
+       // Free any formerly imported keys (this should not happen)
+       if (repo->key) {
+               pakfire_key_unref(repo->key);
+               repo->key = NULL;
+       }
 
-               // Fetch the key's fingerprint
-               const char* fingerprint = pakfire_key_get_fingerprint(*key);
-               if (!fingerprint) {
-                       r = 1;
-                       goto ERROR;
-               }
+       // Import the key
+       r = pakfire_key_import_from_string(&repo->key, repo->pakfire, data, strlen(data));
+       if (r) {
+               ERROR(repo->pakfire, "Could not import key for repository '%s': %m\n",
+                       pakfire_repo_get_name(repo));
+               goto ERROR;
+       }
 
-               // Store the fingerprint
-               r = pakfire_string_set(repo->appdata->key, fingerprint);
-               if (r)
-                       goto ERROR;
+       // If the key could be successfully imported, we will store it in the appdata
+       repo->appdata->key = strdup(data);
+       if (repo->appdata->key) {
+               ERROR(repo->pakfire, "Could not copy the key to appdata: %m\n");
+               r = 1;
+               goto ERROR;
        }
 
 ERROR:
-       if (keys) {
-               for (struct pakfire_key** key = keys; *key; key++)
-                       pakfire_key_unref(*key);
-               free(keys);
-       }
+       if (key)
+               pakfire_key_unref(key);
 
        return r;
 }
@@ -263,7 +254,7 @@ int pakfire_repo_import(struct pakfire* pakfire, struct pakfire_config* config)
                        pakfire_repo_set_mirrorlist_url(repo, mirrors);
 
                // Key
-               FILE* key = pakfire_config_get_fopen(config, *section, "key");
+               const char* key = pakfire_config_get(config, *section, "key", NULL);
                if (key) {
                        r = pakfire_repo_import_key(repo, key);
                        if (r) {
@@ -524,6 +515,9 @@ static void free_repo_appdata(struct pakfire_repo_appdata* appdata) {
        if (!appdata)
                return;
 
+       if (appdata->key)
+               free(appdata->key);
+
        if (appdata->description)
                free(appdata->description);
 
@@ -539,6 +533,10 @@ static void pakfire_repo_free(struct pakfire_repo* repo, const int free_repo) {
                repo_free(repo->repo, 0);
        }
 
+       // Free the key
+       if (repo->key)
+               pakfire_key_unref(repo->key);
+
        if (repo->mirrorlist)
                pakfire_mirrorlist_unref(repo->mirrorlist);
        pakfire_unref(repo->pakfire);
@@ -817,7 +815,20 @@ const char* pakfire_repo_get_path(struct pakfire_repo* repo) {
 }
 
 PAKFIRE_EXPORT struct pakfire_key* pakfire_repo_get_key(struct pakfire_repo* repo) {
-       return pakfire_key_get(repo->pakfire, repo->appdata->key);
+       int r;
+
+       if (!repo->key && repo->appdata->key) {
+               r = pakfire_key_import_from_string(&repo->key, repo->pakfire,
+                       repo->appdata->key, strlen(repo->appdata->key));
+               if (r)
+                       goto ERROR;
+       }
+
+       if (repo->key)
+               return pakfire_key_ref(repo->key);
+
+ERROR:
+       return NULL;
 }
 
 PAKFIRE_EXPORT const char* pakfire_repo_get_mirrorlist_url(struct pakfire_repo* repo) {
@@ -902,9 +913,9 @@ PAKFIRE_EXPORT int pakfire_repo_write_config(struct pakfire_repo* repo, FILE* f)
        // Key
        key = pakfire_repo_get_key(repo);
        if (key) {
-               r = pakfire_key_get_public_key(key, &buffer, &length);
+               r = pakfire_key_export(key, f, PAKFIRE_KEY_EXPORT_MODE_PUBLIC);
                if (r) {
-                       ERROR(repo->pakfire, "Could not fetch public key: %m\n");
+                       ERROR(repo->pakfire, "Could not export the key: %m\n");
                        goto ERROR;
                }
 
index 79cd196b1b4612de5483f793a8f45ea8f0afd890..74606f7a0a6e688fdea95034c43f8662a69cc172 100644 (file)
 #include <json.h>
 #include <uuid/uuid.h>
 
+// OpenSSL
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
 #define PCRE2_CODE_UNIT_WIDTH 8
 #include <pcre2.h>
 
@@ -941,3 +946,77 @@ int pakfire_compile_regex(struct pakfire* pakfire, pcre2_code** regex, const cha
 
        return 0;
 }
+
+// Base64
+
+#define OPENSSL_ERROR_MAX 1024
+
+int pakfire_b64encode(struct pakfire* pakfire, char** output,
+               const void* buffer, const size_t length) {
+       char error[OPENSSL_ERROR_MAX];
+       BIO* b64 = NULL;
+       BIO* bio = NULL;
+       char* p = NULL;
+       int r;
+
+       // Initialize the base64 encoder
+       b64 = BIO_new(BIO_f_base64());
+       if (!b64) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
+
+               ERROR(pakfire, "Could not initialize the base64 encoder: %s\n", error);
+               r = 1;
+               goto ERROR;
+       }
+
+       // Disable line breaks and a trailing newline
+       BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+
+       // Initialize a memory buffer
+       bio = BIO_new(BIO_s_mem());
+       if (!bio) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
+
+               ERROR(pakfire, "Could not initialize memory buffer: %s\n", error);
+               r = 1;
+               goto ERROR;
+       }
+
+       // Connect both things
+       b64 = BIO_push(b64, bio);
+
+       // Write the input
+       r = BIO_write(b64, buffer, length);
+       if (r < 1) {
+               ERR_error_string_n(ERR_get_error(), error, sizeof(error));
+
+               ERROR(pakfire, "%s\n", error);
+               r = 1;
+               goto ERROR;
+       }
+
+       // Flush
+       BIO_flush(b64);
+
+       // Fetch a pointer to the output and determine its length
+       const size_t l = BIO_get_mem_data(b64, &p);
+
+       // Copy the output to the heap
+       *output = strndup(p, l);
+       if (!*output) {
+               ERROR(pakfire, "Could not copy base64 encoded string to heap: %m\n");
+               r = 1;
+               goto ERROR;
+       }
+
+       // Success
+       r = 0;
+
+ERROR:
+       if (bio)
+               BIO_free(bio);
+       if (b64)
+               BIO_free(b64);
+
+       return r;
+}
diff --git a/tests/data/keys/key1.pub b/tests/data/keys/key1.pub
new file mode 100644 (file)
index 0000000..e2f7c87
--- /dev/null
@@ -0,0 +1,2 @@
+untrusted comment: Pakfire Test Key public key
+RWTAZap9ohW221+ZFLwJKs9l9uSbHyJ6ht+bvE6BsJWRF/VC3pRBXxD8
diff --git a/tests/data/keys/key1.sec b/tests/data/keys/key1.sec
new file mode 100644 (file)
index 0000000..595a985
--- /dev/null
@@ -0,0 +1,2 @@
+untrusted comment: Pakfire Test Key secret key
+RWRCSwAAAACp4FboBK3u+pmhh0rTr0F3NWpyMsbUPt7AZap9ohW228SoHTfMv0XDN6XqHElAQ3bmgPGyyYMLlRVbd2FJabNMX5kUvAkqz2X25JsfInqG35u8ToGwlZEX9ULelEFfEPw=
index 5678c92134fa33258bce1b49e6c8e1ca093d447d..8752d821ea9ffe97ce5ccc26f10c92e63f7fe71f 100644 (file)
 #include <pakfire/util.h>
 
 #include "../testsuite.h"
-#include "key.h"
 
-static int test_init(const struct test* t) {
-       struct pakfire_key** keys = NULL;
+static int test_generate(const struct test* t) {
+       struct pakfire_key* key = NULL;
        int r = EXIT_FAILURE;
 
-       // Try loading any keys & delete them all
-       ASSERT_SUCCESS(pakfire_list_keys(t->pakfire, &keys));
-       while (keys && *keys) {
-               struct pakfire_key* key = *keys++;
+       // Try to call pakfire_key_generate() with some invalid inputs
+       ASSERT_ERRNO(pakfire_key_generate(&key, t->pakfire, PAKFIRE_KEY_ALGO_NULL), EINVAL);
 
-               pakfire_key_delete(key);
-               pakfire_key_unref(key);
-       }
+       // Generate a new key using ed25519
+       ASSERT_SUCCESS(pakfire_key_generate(&key, t->pakfire, PAKFIRE_KEY_ALGO_ED25519));
 
-       // Load list of keys again
-       ASSERT_SUCCESS(pakfire_list_keys(t->pakfire, &keys));
+       // Write the public key to the console
+       ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PUBLIC));
 
-       // Must be empty now
-       ASSERT(keys == NULL);
+       // Write the private key to the console
+       ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PRIVATE));
 
        // Everything passed
        r = EXIT_SUCCESS;
 
 FAIL:
+       if (key)
+               pakfire_key_unref(key);
+
        return r;
 }
 
-static int test_generate_key(const struct test* t, const char* algo, const char* userid) {
+static int test_sign(const struct test* t) {
        struct pakfire_key* key = NULL;
-       char* dump = NULL;
        int r = EXIT_FAILURE;
 
-       // Generate a new key
-       ASSERT_SUCCESS(pakfire_key_generate(&key, t->pakfire, algo, userid));
+       const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       const size_t length = strlen(data);
+
+       char* signature = NULL;
+       size_t signature_length = 0;
+
+       // Generate a new key using ed25519
+       ASSERT_SUCCESS(pakfire_key_generate(&key, t->pakfire, PAKFIRE_KEY_ALGO_ED25519));
 
-       // Export the key
-       ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_SECRET));
+       // Write the public key to the console
+       ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PUBLIC));
 
-       // Dump the key details
-       ASSERT(dump = pakfire_key_dump(key));
-       printf("%s\n", dump);
+       // Write the private key to the console
+       ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PRIVATE));
+
+       ASSERT_SUCCESS(pakfire_key_sign(key, stdout, data, length, "UNTRUSTED COMMENT"));
 
        // Everything passed
        r = EXIT_SUCCESS;
@@ -74,29 +79,23 @@ static int test_generate_key(const struct test* t, const char* algo, const char*
 FAIL:
        if (key)
                pakfire_key_unref(key);
-       if (dump)
-               free(dump);
 
        return r;
 }
 
-static int test_generate(const struct test* t) {
+static int test_import_public(const struct test* t) {
        struct pakfire_key* key = NULL;
+       FILE* f = NULL;
        int r = EXIT_FAILURE;
 
-       // Try to call pakfire_key_generate() with some invalid inputs
-       ASSERT_ERRNO(pakfire_key_generate(&key, t->pakfire, NULL, NULL), EINVAL);
-       ASSERT_ERRNO(pakfire_key_generate(&key, t->pakfire, "rsa2048", NULL), EINVAL);
-       ASSERT_ERRNO(pakfire_key_generate(&key, t->pakfire, NULL, "Invalid Test Key"), EINVAL);
-
-       // Generate a new key using RSA2048
-       ASSERT_SUCCESS(test_generate_key(t, "rsa2048", "Test Key #1"));
+       // Open the public key
+       ASSERT(f = fopen(TEST_DATA_DIR "/keys/key1.pub", "r"));
 
-       // Generate a new key using ed25519
-       ASSERT_SUCCESS(test_generate_key(t, "ed25519", "Test Key #2"));
+       // Try to import the key
+       ASSERT_SUCCESS(pakfire_key_import(&key, t->pakfire, f));
 
-       // Try to generate a key with the same ID
-       ASSERT_ERRNO(pakfire_key_generate(&key, t->pakfire, "rsa2048", "Test Key #1"), EINVAL);
+       // Write the imported key to the console
+       ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PUBLIC));
 
        // Everything passed
        r = EXIT_SUCCESS;
@@ -104,58 +103,43 @@ static int test_generate(const struct test* t) {
 FAIL:
        if (key)
                pakfire_key_unref(key);
+       if (f)
+               fclose(f);
 
        return r;
 }
 
-static int test_import_export(const struct test* t) {
-       // Try to delete the key just in case it
-       // has been imported before
-       struct pakfire_key* key = pakfire_key_get(t->pakfire, TEST_KEY_FINGERPRINT);
-       if (key) {
-               pakfire_key_delete(key);
-               pakfire_key_unref(key);
-       }
-
-#if 0
-       // Import a key
-       struct pakfire_key** keys = pakfire_key_import(t->pakfire, TEST_KEY_DATA);
-
-       // We should have a list with precisely one key object
-       ASSERT(keys);
-       ASSERT(keys[0] != NULL);
-       ASSERT(keys[1] == NULL);
-
-       // Get the imported key
-       key = *keys;
+static int test_import_secret(const struct test* t) {
+       struct pakfire_key* key = NULL;
+       FILE* f = NULL;
+       int r = EXIT_FAILURE;
 
-       // Check the fingerprint
-       const char* fingerprint = pakfire_key_get_fingerprint(key);
-       ASSERT(strcmp(fingerprint, TEST_KEY_FINGERPRINT) == 0);
+       // Open the public key
+       ASSERT(f = fopen(TEST_DATA_DIR "/keys/key1.sec", "r"));
 
-       // Dump key description
-       char* dump = pakfire_key_dump(key);
-       ASSERT(dump);
-       LOG("%s\n", dump);
-       free(dump);
+       // Try to import the key
+       ASSERT_SUCCESS(pakfire_key_import(&key, t->pakfire, f));
 
-       // Export the key
-       char* data = pakfire_key_export(key, 0);
-       ASSERT(data);
+       // Write the imported key to the console
+       ASSERT_SUCCESS(pakfire_key_export(key, stdout, PAKFIRE_KEY_EXPORT_MODE_PRIVATE));
 
-       LOG("Exported key:\n%s\n", data);
-       free(data);
+       // Everything passed
+       r = EXIT_SUCCESS;
 
-       pakfire_key_unref(key);
-#endif
+FAIL:
+       if (key)
+               pakfire_key_unref(key);
+       if (f)
+               fclose(f);
 
-       return EXIT_SUCCESS;
+       return r;
 }
 
 int main(int argc, const char* argv[]) {
-       testsuite_add_test(test_init);
        testsuite_add_test(test_generate);
-       testsuite_add_test(test_import_export);
+       testsuite_add_test(test_sign);
+       testsuite_add_test(test_import_public);
+       testsuite_add_test(test_import_secret);
 
        return testsuite_run(argc, argv);
 }
diff --git a/tests/libpakfire/key.h b/tests/libpakfire/key.h
deleted file mode 100644 (file)
index 95d285c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*#############################################################################
-#                                                                             #
-# 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/>.       #
-#                                                                             #
-#############################################################################*/
-
-const char* TEST_KEY_FINGERPRINT = "E63B4976A575A3B2544AC15E726D8B0B0889B04E";
-
-const char* TEST_KEY_DATA = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n"
-"mQINBE/ndRQBEAC5ykX6wgPdR42ZkTdrcVS9fIACn/n/ed7K/dWlUtANnAtoH27Qp+I/vKy9\n"
-"DwGUjDe5ST8l4td+gzZNwWowTnLr6zULG+dBDPNL1SZrL7sxLfjuEyOAAFcMTI8hKqwCQfSz\n"
-"OJVX4X7mfSDgewqFjDO1a1gkJUXnq8xMNJa6fTH61qVPXmwBpR4JgzrtH4FmvuXjocKZ4+/B\n"
-"NwD80ChfiwwNjwTv0ykdXhV6aEtqg9sfFRB/BGUIBDUOlG6i8VCNQ0X1rAcyO2waj6cAfYVE\n"
-"HbD4POMIWhaBvfKnYUuUyPoSDjcgIWIrHmdBHuM/zbLjAfIoh/Lk16UnU6DBjsMdtq6d9HWD\n"
-"OWRQOXigwKHiRZD9QQDPxTb8w6EAu/UFzHNUCD7O0rS2KmugZMk/Q0ijhVCfC6MXTu7Vjg3c\n"
-"tjf7ZE2kvhKs5I6j3lTCLm23WYcRefKJQ/9Ab1d6bYoOwNpQFdP0duYyP2TC1cSC5Cs8h7pE\n"
-"nI1yB9B+Fu6fqNyIhgo9fbh29+F8K/KYT0UifsTvBNTv2bf+23IbFR3EC3WWEdvars1h9mTK\n"
-"g8bbyKNxXrWXrPUb+TWovaTpzpRNqOYDa5tqh9Q/0e1mkNcjJbBK/2HxAT4hi69Dfswr0cYh\n"
-"IwpH3fTwlZPpBjEOVz5VyAaZyjjJHweRhz5YJUgPt7J9/tTmGQARAQABtEVJUEZpcmUgQnVp\n"
-"bGRzZXJ2ZXIgY29ybmVsaXVzLmlwZmlyZS5vcmcgPHBha2ZpcmUtYnVpbGRlcnNAaXBmaXJl\n"
-"Lm9yZz6JAjgEEwECACIFAk/ndRQCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEHJt\n"
-"iwsIibBOdqsP/1EVKVgFxiMVcRTP5VYV2+EV/CaiaqMzC488AGRq8LYMzq/hqj0w+lbCl6AG\n"
-"25Aqf6UX8VMgkPr5pIy/IZqZgQ0N7fX6Vw0mhR/2zAHItvuff8zCM2Sp682CRahn1SB9oWjl\n"
-"bJZwHJPVkLVqAxs5f1EyXstl8NNrVJQ0rZKWvfTKJL6kCYitnNuat4BB/uv2aNB8MiMlwJj6\n"
-"DtO6uGagw3lkR9w+PL0lW2auQqE6Ia6CIdOT43qQ/Is7SnmL5uS5/uwNgdZ1ayCMPM+xeJrH\n"
-"A7MTQKVDcyTmkIriO7qRaaPsPkhqfD/vjurWQ+Hx9XTUUk3QeCpZfXLGB+ZNLg2+kxanSoQ0\n"
-"JbB8V7OMOi7Z8y0U0vXKTn1cKIzrXB1/GvwpYPZAmFgcOqXoNF3Qs7ilud3bxomG8nBHWNBA\n"
-"1w+rzMYQbwCow7GkknniaB+ZzkPB+8+1jul4U5rtGeFyloyHy6WO2WKk7nsou/i3vfpVHRzh\n"
-"9XVkEYesGrAIJqrpfJYgAbzRSUyPoFoIBhC7p8emKr/TTzzc90s5EPlqkxE/BRPvkqW+4HjS\n"
-"ybOFv4fii7qGdpNrnXTACB2v06Y+TpUGXVA5+Ac+5Zn5F/++tUnvZ9eCT1VmUhw+wDV7qQtq\n"
-"gVwRjTWnu8cc9uoZbKK1Qifehl11xi4hp+YZmv/7eOg1LWeR\n"
-"=XdHO\n\n"
-"-----END PGP PUBLIC KEY BLOCK-----\n";