commit c67351d: [Feature] Add cryptobox method to generate dkim keypairs

Vsevolod Stakhov vsevolod at highsecure.ru
Fri Apr 26 15:49:12 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-04-26 16:42:01 +0100
URL: https://github.com/rspamd/rspamd/commit/c67351d64510b93f1e040e0fa1bcbccb7a015a35 (HEAD -> master)

[Feature] Add cryptobox method to generate dkim keypairs

---
 src/lua/lua_cryptobox.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c
index c196a0897..cb531a5e1 100644
--- a/src/lua/lua_cryptobox.c
+++ b/src/lua/lua_cryptobox.c
@@ -96,6 +96,7 @@ LUA_FUNCTION_DEF (cryptobox, decrypt_file);
 LUA_FUNCTION_DEF (cryptobox, encrypt_cookie);
 LUA_FUNCTION_DEF (cryptobox, decrypt_cookie);
 LUA_FUNCTION_DEF (cryptobox, pbkdf);
+LUA_FUNCTION_DEF (cryptobox, gen_dkim_keypair);
 
 static const struct luaL_reg cryptoboxlib_f[] = {
 	LUA_INTERFACE_DEF (cryptobox, verify_memory),
@@ -109,6 +110,7 @@ static const struct luaL_reg cryptoboxlib_f[] = {
 	LUA_INTERFACE_DEF (cryptobox, encrypt_cookie),
 	LUA_INTERFACE_DEF (cryptobox, decrypt_cookie),
 	LUA_INTERFACE_DEF (cryptobox, pbkdf),
+	LUA_INTERFACE_DEF (cryptobox, gen_dkim_keypair),
 	{NULL, NULL}
 };
 
@@ -2197,6 +2199,139 @@ lua_cryptobox_pbkdf (lua_State *L)
 	return 1;
 }
 
+/***
+ * @function rspamd_cryptobox.gen_dkim_keypair([alg, [nbits]])
+ * Generates DKIM keypair. Returns 2 base64 strings as rspamd_text: privkey and pubkey
+ * @param {string} alg optional algorithm (rsa default, can be ed25519)
+ * @param {number} nbits optional number of bits for rsa (default 1024)
+ * @return {rspamd_text,rspamd_text} private key and public key as base64 encoded strings
+ */
+static gint
+lua_cryptobox_gen_dkim_keypair (lua_State *L)
+{
+	const gchar *alg_str = "rsa";
+	guint nbits = 1024;
+	struct rspamd_lua_text *priv_out, *pub_out;
+
+	if (lua_type (L, 1) == LUA_TSTRING) {
+		alg_str = lua_tostring (L, 1);
+	}
+
+	if (lua_type (L, 2) == LUA_TNUMBER) {
+		nbits = lua_tointeger (L, 2);
+	}
+
+	if (strcmp (alg_str, "rsa") == 0) {
+		BIGNUM *e;
+		RSA *r;
+		EVP_PKEY *pk;
+
+		e = BN_new ();
+		r = RSA_new ();
+		pk = EVP_PKEY_new ();
+
+		if (BN_set_word (e, RSA_F4) != 1) {
+			BN_free (e);
+			RSA_free (r);
+			EVP_PKEY_free (pk);
+
+			return luaL_error (L, "BN_set_word failed");
+		}
+
+		if (RSA_generate_key_ex (r, nbits, e, NULL) != 1) {
+			BN_free (e);
+			RSA_free (r);
+			EVP_PKEY_free (pk);
+
+			return luaL_error (L, "RSA_generate_key_ex failed");
+		}
+
+		if (EVP_PKEY_set1_RSA (pk, r) != 1) {
+			BN_free (e);
+			RSA_free (r);
+			EVP_PKEY_free (pk);
+
+			return luaL_error (L, "EVP_PKEY_set1_RSA failed");
+		}
+
+		BIO *mbio;
+		gint rc, len;
+		guchar *data;
+		gchar *b64_data;
+		gsize b64_len;
+
+		mbio = BIO_new (BIO_s_mem ());
+
+		/* Process private key */
+		rc = i2d_RSAPrivateKey_bio (mbio, r);
+		len = BIO_get_mem_data (mbio, &data);
+
+		b64_data = rspamd_encode_base64 (data, len, -1, &b64_len);
+
+		priv_out = lua_newuserdata (L, sizeof (*priv_out));
+		rspamd_lua_setclass (L, "rspamd{text}", -1);
+		priv_out->start = b64_data;
+		priv_out->len = b64_len;
+		priv_out->flags = RSPAMD_TEXT_FLAG_OWN|RSPAMD_TEXT_FLAG_WIPE;
+
+		/* Process public key */
+		BIO_reset (mbio);
+		rc = i2d_RSA_PUBKEY_bio (mbio, r);
+		len = BIO_get_mem_data (mbio, &data);
+
+		b64_data = rspamd_encode_base64 (data, len, -1, &b64_len);
+
+		pub_out = lua_newuserdata (L, sizeof (*pub_out));
+		rspamd_lua_setclass (L, "rspamd{text}", -1);
+		pub_out->start = b64_data;
+		pub_out->len = b64_len;
+		pub_out->flags = RSPAMD_TEXT_FLAG_OWN;
+
+		BN_free (e);
+		RSA_free (r);
+		EVP_PKEY_free (pk);
+		BIO_free (mbio);
+	}
+	else if (strcmp (alg_str, "ed25519") == 0) {
+		rspamd_sig_pk_t pk;
+		rspamd_sig_sk_t sk;
+		gchar *b64_data;
+		gsize b64_len;
+
+		rspamd_cryptobox_keypair_sig (pk, sk, RSPAMD_CRYPTOBOX_MODE_25519);
+
+		/* Process private key */
+		b64_data = rspamd_encode_base64 (sk,
+				rspamd_cryptobox_sk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519),
+				-1, &b64_len);
+
+		priv_out = lua_newuserdata (L, sizeof (*priv_out));
+		rspamd_lua_setclass (L, "rspamd{text}", -1);
+		priv_out->start = b64_data;
+		priv_out->len = b64_len;
+		priv_out->flags = RSPAMD_TEXT_FLAG_OWN|RSPAMD_TEXT_FLAG_WIPE;
+
+		/* Process public key */
+		b64_data = rspamd_encode_base64 (pk,
+				rspamd_cryptobox_pk_sig_bytes (RSPAMD_CRYPTOBOX_MODE_25519),
+				-1, &b64_len);
+
+		pub_out = lua_newuserdata (L, sizeof (*pub_out));
+		rspamd_lua_setclass (L, "rspamd{text}", -1);
+		pub_out->start = b64_data;
+		pub_out->len = b64_len;
+		pub_out->flags = RSPAMD_TEXT_FLAG_OWN;
+
+		rspamd_explicit_memzero (pk, sizeof (pk));
+		rspamd_explicit_memzero (sk, sizeof (sk));
+	}
+	else {
+		return luaL_error (L, "invalid algorithm %s", alg_str);
+	}
+
+	return 2;
+}
+
 static gint
 lua_load_pubkey (lua_State * L)
 {


More information about the Commits mailing list