Browse Source

[Feature] Support ed25519 dkim keys generation

tags/1.9.0
Vsevolod Stakhov 5 years ago
parent
commit
8b5cd205ad
3 changed files with 135 additions and 24 deletions
  1. 1
    12
      src/libutil/str_util.c
  2. 18
    0
      src/libutil/str_util.h
  3. 116
    12
      src/rspamadm/dkim_keygen.c

+ 1
- 12
src/libutil/str_util.c View File

@@ -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)
{

+ 18
- 0
src/libutil/str_util.h View File

@@ -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

+ 116
- 12
src/rspamadm/dkim_keygen.c View File

@@ -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)
{

Loading…
Cancel
Save