commit 8b5cd20: [Feature] Support ed25519 dkim keys generation
Vsevolod Stakhov
vsevolod at highsecure.ru
Tue Feb 26 14:56:03 UTC 2019
Author: Vsevolod Stakhov
Date: 2019-02-26 14:54:40 +0000
URL: https://github.com/rspamd/rspamd/commit/8b5cd205ada30cb3e05d154efb078fb69a53c358 (HEAD -> master)
[Feature] Support ed25519 dkim keys generation
---
src/libutil/str_util.c | 13 +----
src/libutil/str_util.h | 18 +++++++
src/rspamadm/dkim_keygen.c | 128 ++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 135 insertions(+), 24 deletions(-)
diff --git a/src/libutil/str_util.c b/src/libutil/str_util.c
index 0defa2acf..ac7471ada 100644
--- a/src/libutil/str_util.c
+++ b/src/libutil/str_util.c
@@ -734,18 +734,7 @@ rspamd_decode_base32 (const gchar *in, gsize inlen, gsize *outlen)
}
-
-/**
- * Decode string using base32 encoding
- * @param in input
- * @param inlen input length
- * @param out output buf (may overlap with `in`)
- * @param outlen output buf len
- * @return TRUE if in is valid base32 and `outlen` is enough to encode `inlen`
- */
-
-
-static gchar *
+gchar *
rspamd_encode_base64_common (const guchar *in, gsize inlen, gint str_len,
gsize *outlen, gboolean fold, enum rspamd_newlines_type how)
{
diff --git a/src/libutil/str_util.h b/src/libutil/str_util.h
index 34c1271d4..9145b97b4 100644
--- a/src/libutil/str_util.h
+++ b/src/libutil/str_util.h
@@ -184,6 +184,7 @@ gint rspamd_decode_base32_buf (const gchar *in, gsize inlen,
gint rspamd_encode_hex_buf (const guchar *in, gsize inlen, gchar *out,
gsize outlen);
+
/**
* Decode string using hex encoding
* @param in input
@@ -195,6 +196,23 @@ gint rspamd_encode_hex_buf (const guchar *in, gsize inlen, gchar *out,
gssize rspamd_decode_hex_buf (const gchar *in, gsize inlen,
guchar *out, gsize outlen);
+/**
+ * Common version of base64 encoder
+ * @param in
+ * @param inlen
+ * @param str_len
+ * @param outlen
+ * @param fold
+ * @param how
+ * @return
+ */
+gchar *
+rspamd_encode_base64_common (const guchar *in,
+ gsize inlen,
+ gint str_len,
+ gsize *outlen,
+ gboolean fold,
+ enum rspamd_newlines_type how);
/**
* Encode string using base64 encoding
* @param in input
diff --git a/src/rspamadm/dkim_keygen.c b/src/rspamadm/dkim_keygen.c
index 86b228d01..86f786295 100644
--- a/src/rspamadm/dkim_keygen.c
+++ b/src/rspamadm/dkim_keygen.c
@@ -17,6 +17,8 @@
#include "rspamadm.h"
#include "printf.h"
#include "str_util.h"
+#include "libcryptobox/cryptobox.h"
+#include "contrib/libottery/ottery.h"
#include "lua/lua_common.h"
#include <openssl/rsa.h>
#include <openssl/bn.h>
@@ -26,6 +28,7 @@ static gchar *privkey_file = NULL;
static gchar *selector = NULL;
static gchar *domain = NULL;
static guint bits = 1024;
+static gchar *type = "rsa";
static void rspamadm_dkim_keygen (gint argc, gchar **argv,
const struct rspamadm_command *cmd);
@@ -50,6 +53,8 @@ static GOptionEntry entries[] = {
"Save private key in the specified file", NULL},
{"bits", 'b', 0, G_OPTION_ARG_INT, &bits,
"Set key length to N bits (1024 by default)", NULL},
+ {"type", 't', 0, G_OPTION_ARG_STRING, &type,
+ "Key type: rsa or ed25519 (rsa by default)", NULL},
{NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}
};
@@ -76,8 +81,9 @@ rspamadm_dkim_keygen_help (gboolean full_help, const struct rspamadm_command *cm
}
static void
-rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector,
- const gchar *priv_fname, const gchar *pub_fname, guint keylen)
+rspamd_dkim_generate_rsa_keypair (const gchar *domain, const gchar *selector,
+ const gchar *priv_fname, const gchar *pub_fname,
+ guint keylen)
{
BIGNUM *e;
RSA *r;
@@ -109,8 +115,7 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector,
priv_fname, strerror (errno));
exit (EXIT_FAILURE);
}
- }
- else {
+ } else {
privout = BIO_new_fp (stdout, 0);
}
@@ -125,7 +130,7 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector,
BIO_free (privout);
fflush (stdout);
- pubout = BIO_new (BIO_s_mem());
+ pubout = BIO_new (BIO_s_mem ());
rc = i2d_RSA_PUBKEY_bio (pubout, r);
publen = BIO_get_mem_data (pubout, &pubdata);
@@ -141,18 +146,16 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector,
pub_fname, strerror (errno));
exit (EXIT_FAILURE);
}
- }
- else {
+ } else {
pubfile = stdout;
}
if (b64_len < 255 - 2) {
rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=rsa; \"\n"
- "\t\"p=%s\" ) ;\n",
+ "\t\"p=%s\" ) ;\n",
selector ? selector : "selector",
b64_data);
- }
- else {
+ } else {
guint i;
gint step = 253, remain = b64_len;
@@ -162,8 +165,7 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector,
for (i = 0; i < b64_len; i += step, remain -= step) {
if (i == 0) {
rspamd_fprintf (pubfile, "\t\"p=%*s\"\n", MIN(step, remain), &b64_data[i]);
- }
- else {
+ } else {
step = 255;
rspamd_fprintf (pubfile, "\t\"%*s\"\n", MIN(step, remain), &b64_data[i]);
}
@@ -183,6 +185,108 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector,
BN_free (e);
}
+static void
+rspamd_dkim_generate_ed25519_keypair (const gchar *domain, const gchar *selector,
+ const gchar *priv_fname, const gchar *pub_fname,
+ guint keylen)
+{
+ rspamd_sig_sk_t ed_sk;
+ rspamd_sig_pk_t ed_pk;
+ gchar *base64_pk, *base64_sk;
+ FILE *pubfile = NULL, *privfile = NULL;
+
+ rspamd_cryptobox_keypair_sig (ed_pk, ed_sk, RSPAMD_CRYPTOBOX_MODE_25519);
+ /* Just encode seed, not the full sk */
+ base64_sk = rspamd_encode_base64_common (ed_sk, 32, 0, NULL, FALSE,
+ RSPAMD_TASK_NEWLINES_LF);
+ base64_pk = rspamd_encode_base64_common (ed_pk, sizeof (ed_pk), 0, NULL, FALSE,
+ RSPAMD_TASK_NEWLINES_LF);
+
+ /* Cleanup sensitive data */
+ rspamd_explicit_memzero (ed_sk, sizeof (ed_sk));
+
+ if (priv_fname) {
+ privfile = fopen (priv_fname, "w");
+
+ if (privfile == NULL) {
+ rspamd_fprintf (stderr, "cannot open output file %s: %s\n",
+ priv_fname, strerror (errno));
+ rspamd_explicit_memzero (base64_sk, strlen (base64_sk));
+ g_free (base64_sk);
+ g_free (base64_pk);
+ exit (EXIT_FAILURE);
+ }
+ }
+ else {
+ privfile = stdout;
+ }
+
+ if (rspamd_fprintf (privfile, "%s\n", base64_sk) == -1) {
+ rspamd_fprintf (stderr, "cannot write to output file %s: %s\n",
+ priv_fname, strerror (errno));
+ rspamd_explicit_memzero (base64_sk, strlen (base64_sk));
+ g_free (base64_sk);
+ g_free (base64_pk);
+
+ if (privfile != stdout) {
+ fclose (privfile);
+ }
+
+ exit (EXIT_FAILURE);
+ }
+
+ if (privfile != stdout) {
+ fclose (privfile);
+ }
+
+ if (pub_fname) {
+ pubfile = fopen (pub_fname, "w");
+
+ if (pubfile == NULL) {
+ rspamd_fprintf (stderr, "cannot open output file %s: %s\n",
+ pub_fname, strerror (errno));
+ rspamd_explicit_memzero (base64_sk, strlen (base64_sk));
+ g_free (base64_sk);
+ g_free (base64_pk);
+ exit (EXIT_FAILURE);
+ }
+ }
+ else {
+ pubfile = stdout;
+ }
+
+ rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=ed25519; \"\n"
+ "\t\"p=%s\" ) ;\n",
+ selector ? selector : "selector",
+ base64_pk);
+
+ if (pubfile != stdout) {
+ fclose (pubfile);
+ }
+
+ rspamd_explicit_memzero (base64_sk, strlen (base64_sk));
+ g_free (base64_sk);
+ g_free (base64_pk);
+}
+
+static void
+rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector,
+ const gchar *priv_fname, const gchar *pub_fname, guint keylen)
+{
+ if (strcmp (type, "rsa") == 0) {
+ rspamd_dkim_generate_rsa_keypair (domain, selector, priv_fname,
+ pub_fname, keylen);
+ }
+ else if (strcmp (type, "ed25519") == 0) {
+ rspamd_dkim_generate_ed25519_keypair (domain, selector, priv_fname,
+ pub_fname, keylen);
+ }
+ else {
+ fprintf (stderr, "invalid key type: %s\n", type);
+ exit (EXIT_FAILURE);
+ }
+}
+
static gint
rspamadm_dkim_keygen_lua_generate (lua_State *L)
{
More information about the Commits
mailing list