#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>
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);
"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}
};
}
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;
priv_fname, strerror (errno));
exit (EXIT_FAILURE);
}
- }
- else {
+ } else {
privout = BIO_new_fp (stdout, 0);
}
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);
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;
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]);
}
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)
{