aboutsummaryrefslogtreecommitdiffstats
path: root/lualib
diff options
context:
space:
mode:
authorIvan Stakhov <50211739+left-try@users.noreply.github.com>2024-09-18 19:10:59 +0300
committerGitHub <noreply@github.com>2024-09-18 17:10:59 +0100
commit92b679d17ca41f85009c9e33cdd5967f955b5557 (patch)
treeeeef4e285e0f00b1ec5a55338e2af33db802249b /lualib
parent206195f2197631a3625a0c6b7d17eb55da86ce46 (diff)
downloadrspamd-92b679d17ca41f85009c9e33cdd5967f955b5557.tar.gz
rspamd-92b679d17ca41f85009c9e33cdd5967f955b5557.zip
[Feature] Add rspamadm secretbox command
* [Minor] Small fix for error messages * [Feature] Create rspamadm util to decrypt header * [Feature] Create python example to encrypt/decrypt header * [Minor] Small clean up * [Minor] Change c-rspamadm util to lua-rspamadm util * [Minor] Small clean up * [Minor] Add some debug * [Feature] Add secretbox command * [Minor] Debug * [Minor] Add additional return for encrypted string(noce + encrypted string * [Minor] Small debug * [Minor] Add a way to provide encrypted text concatenated with nonce * [Minor] Add nonce to encrypt text * [Minor] Clean up * [Minor] Clean up unused variable * [Minor] Small fix * [Minor] Fix return issue * [Minor] Add blake2b for key derivation * [Minor] Small upgrade to debug * [Minor] Small clean up * [Minor] Change return to more convenient form * [Minor] Change print to test form * [Test] Provide tests for encrypt/decrypt with rspamadm util and python script * [Minor] Change python to python3 * [Minor] Add stderr check * [Minor] Make the function return nonce+text * [Minor] Change unit tests to new return format * [Minor] Add flag to manage encodings * [Minor] Add --encoding argument to manage encodings * [Minor] Change tests for new input format * [Minor] Fix lua format * [Minor] Small fix * [Minor] Provide full support for new return format of maybe_encrypt_header * [Test] Test small fix * [Test] Small fix * [Minor] Clean up * [Minor] Small fix for name of variable * [Minor] Small clean up * [Minor] Change format of command to a mre convenient * [Minor] Change tests to be same as a format of a command * [Minor] Change description of flags * [Minor] Small fix --------- Co-authored-by: Ivan Stakhov <50211739+LeftTry@users.noreply.github.com>
Diffstat (limited to 'lualib')
-rw-r--r--lualib/lua_util.lua11
-rw-r--r--lualib/rspamadm/secretbox.lua157
2 files changed, 163 insertions, 5 deletions
diff --git a/lualib/lua_util.lua b/lualib/lua_util.lua
index ffc07842e..62b38c87e 100644
--- a/lualib/lua_util.lua
+++ b/lualib/lua_util.lua
@@ -1305,12 +1305,12 @@ exports.maybe_encrypt_header = function(header, settings, prefix)
local rspamd_secretbox = require "rspamd_cryptobox_secretbox"
if not header or header == '' then
- logger.errx(rspamd_config, "Header: %s is empty or nil", header)
+ logger.errx(rspamd_config, "Header is empty or nil. Header: %s", header)
return nil
elseif settings[prefix .. '_encrypt'] then
local key = settings[prefix .. '_key']
if not key or key == '' then
- logger.errx(rspamd_config, "Key: %s is empty or nil", key)
+ logger.errx(rspamd_config, "Key is empty or nil. Key: %s", key)
return header
end
local cryptobox = rspamd_secretbox.create(key)
@@ -1322,7 +1322,8 @@ exports.maybe_encrypt_header = function(header, settings, prefix)
else
encrypted_header = cryptobox:encrypt(header, nonce)
end
- return encrypted_header, nonce
+ encrypted_header = nonce .. encrypted_header
+ return encrypted_header
end
end
@@ -1342,12 +1343,12 @@ exports.maybe_decrypt_header = function(encrypted_header, settings, prefix, nonc
local rspamd_secretbox = require "rspamd_cryptobox_secretbox"
if not encrypted_header or encrypted_header == '' then
- logger.errx(rspamd_config, "Encoded header: %s is empty or nil")
+ logger.errx(rspamd_config, "Encrypted header is empty or nil. Encrypted header: %s", encrypted_header)
return nil
elseif settings[prefix .. '_encrypt'] then
local key = settings[prefix .. '_key']
if not key or key == '' then
- logger.errx(rspamd_config, "Key: %s is empty or nil")
+ logger.errx(rspamd_config, "Key is empty or nil. Key: %s", key)
return encrypted_header
end
local cryptobox = rspamd_secretbox.create(key)
diff --git a/lualib/rspamadm/secretbox.lua b/lualib/rspamadm/secretbox.lua
new file mode 100644
index 000000000..3ab10cee0
--- /dev/null
+++ b/lualib/rspamadm/secretbox.lua
@@ -0,0 +1,157 @@
+local util = require 'lua_util'
+local rspamd_util = require 'rspamd_util'
+local argparse = require 'argparse'
+
+local parser = argparse()
+ :name "secretbox"
+ :description "Encrypt/decrypt given text with given key and nonce"
+ :help_description_margin(32)
+ :command_target('command')
+ :require_command(true)
+
+parser:mutex(
+ parser:flag '-R --raw'
+ :description('Encrypted text(and nonce if it is there) will be given in raw'),
+ parser:flag '-H --hex'
+ :description('Encrypted text(and nonce if it is there) will be given in hex'),
+ parser:flag '-b --base32'
+ :description('Encrypted text(and nonce if it is there) will be given in base32'),
+ parser:flag '-B --base64'
+ :description('Encrypted text(and nonce if it is there) will be given in base64')
+)
+
+local decrypt = parser:command 'decrypt'
+ :description 'Decrypt text with given key and nonce'
+
+decrypt:option "-t --text"
+ :description("Encrypted text(Base 64)")
+ :argname("<text>")
+decrypt:option "-k --key"
+ :description("Key used to encrypt text")
+ :argname("<key>")
+decrypt:option "-n --nonce"
+ :description("Nonce used to encrypt text(Base 64)")
+ :argname("<nonce>")
+ :default(nil)
+
+local encrypt = parser:command 'encrypt'
+ :description 'Encrypt text with given key'
+
+encrypt:option "-t --text"
+ :description("Text to encrypt")
+ :argname("<text>")
+encrypt:option "-k --key"
+ :description("Key to encrypt text")
+ :argname("<key>")
+encrypt:option "-n --nonce"
+ :description("Nonce to encrypt text(Base 64)")
+ :argname("<nonce>")
+ :default(nil)
+
+local function set_up_encoding(args, type, text)
+ local function fromhex(str)
+ return (str:gsub('..', function (cc)
+ return string.char(tonumber(cc, 16))
+ end))
+ end
+
+ local function tohex(str)
+ return (str:gsub('.', function (c)
+ return string.format('%02X', string.byte(c))
+ end))
+ end
+
+ local output = text
+
+ if type == 'encode' then
+ if args.hex then
+ output = tohex(text)
+ elseif args.base32 then
+ output = rspamd_util.encode_base32(text)
+ elseif args.base64 then
+ output = rspamd_util.encode_base64(text)
+ end
+ elseif type == 'decode' then
+ if args.hex then
+ output = fromhex(text)
+ elseif args.base32 then
+ output = rspamd_util.decode_base32(text)
+ elseif args.base64 then
+ output = rspamd_util.decode_base64(text)
+ end
+ end
+
+ return output
+end
+
+local function decryption_handler(args)
+ local settings = {
+ prefix = 'dec',
+ dec_encrypt = true,
+ dec_key = args.key
+ }
+
+ local decrypted_header = ''
+ if(args.nonce ~= nil) then
+ local decoded_text = set_up_encoding(args, 'decode', tostring(args.text))
+ local decoded_nonce = set_up_encoding(args, 'decode', tostring(args.nonce))
+
+ decrypted_header = util.maybe_decrypt_header(decoded_text, settings, settings.prefix, decoded_nonce)
+ else
+ local text_with_nonce = set_up_encoding(args, 'decode', tostring(args.text))
+ local nonce = string.sub(tostring(text_with_nonce), 1, 24)
+ local text = string.sub(tostring(text_with_nonce), 25)
+
+ decrypted_header = util.maybe_decrypt_header(text, settings, settings.prefix, nonce)
+ end
+
+ if decrypted_header ~= nil then
+ print(decrypted_header)
+ else
+ print('The decryption failed. Please check the correctness of the arguments given.')
+ end
+end
+
+local function encryption_handler(args)
+ local settings = {
+ prefix = 'dec',
+ dec_encrypt = true,
+ dec_key = args.key,
+ }
+
+ if args.nonce ~= nil then
+ settings.dec_nonce = set_up_encoding(args, 'decode', tostring(args.nonce))
+ end
+
+ local encrypted_text = util.maybe_encrypt_header(args.text, settings, settings.prefix)
+
+ if encrypted_text ~= nil then
+ print(set_up_encoding(args, 'encode', tostring(encrypted_text)))
+ else
+ print('The encryption failed. Please check the correctness of the arguments given.')
+ end
+end
+
+local command_handlers = {
+ decrypt = decryption_handler,
+ encrypt = encryption_handler,
+}
+
+local function handler(args)
+ local cmd_opts = parser:parse(args)
+
+ local f = command_handlers[cmd_opts.command]
+ if not f then
+ parser:error(string.format("command isn't implemented: %s",
+ cmd_opts.command))
+ end
+ f(cmd_opts)
+end
+
+
+return {
+ name = 'secret_box',
+ aliases = { 'secretbox', 'secret_box' },
+ handler = handler,
+ description = parser._description
+} \ No newline at end of file