From ae53944eec8b20ce389712de5d1cc10b5e6c35bf Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 3 Jun 2018 21:54:00 +0100 Subject: [PATCH] [Feature] Implement signing using `rspamadm keypair` --- lualib/rspamadm/keypair.lua | 75 ++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/lualib/rspamadm/keypair.lua b/lualib/rspamadm/keypair.lua index b5155dfaa..69b50b921 100644 --- a/lualib/rspamadm/keypair.lua +++ b/lualib/rspamadm/keypair.lua @@ -16,6 +16,7 @@ limitations under the License. local argparse = require "argparse" local rspamd_keypair = require "rspamd_cryptobox_keypair" +local rspamd_crypto = require "rspamd_cryptobox" local ucl = require "ucl" -- Define command line options @@ -32,6 +33,9 @@ generate:flag "-s --sign" :description "Generates a sign keypair instead of the encryption one" generate:flag "-n --nist" :description "Uses nist encryption algorithm" +generate:option "-o --output" + :description "Write keypair to file" + :argname "" generate:mutex( generate:flag "-j --json" :description "Output JSON instead of UCL", @@ -40,6 +44,20 @@ generate:mutex( :default(true) ) +local sign = parser:command "sign sig s" + :description "Signs a file using keypair" +sign:option "-k --keypair" + :description "Keypair to use" + :argname "" +sign:option "-s --suffix" + :description "Suffix for signature" + :argname "" + :default("sig") +sign:argument "file" + :description "File to sign" + :argname "" + :args "*" + -- Default command is generate, so duplicate options parser:flag "-s --sign" :description "Generates a sign keypair instead of the encryption one" @@ -52,6 +70,9 @@ parser:mutex( :description "Output UCL" :default(true) ) +parser:option "-o --output" + :description "Write keypair to file" + :argname "" local function handler(args) local opts = parser:parse(args) @@ -75,7 +96,59 @@ local function handler(args) if opts.json then format = 'json' end - io.write(ucl.to_format(kp, format)) + + if opts.output then + local out = io.open(opts.output, 'w') + if not out then + parser:error('cannot open output to write: ' .. opts.output) + end + out:write(ucl.to_format(kp, format)) + out:close() + else + io.write(ucl.to_format(kp, format)) + end + + elseif command == 'sign' then + if opts.file then + if type(opts.file) == 'string' then + opts.file = {opts.file} + end + else + parser:error('no files to sign') + end + if not opts.keypair then + parser:error("no keypair specified") + end + + local ucl_parser = ucl.parser() + local res,err = ucl_parser:parse_file(opts.keypair) + + if not res then + parser:error(string.format('cannot load %s: %s', opts.keypair, err)) + end + + local kp = rspamd_keypair.load(ucl_parser:get_object()) + + if not kp then + parser:error("cannot load keypair: " .. opts.keypair) + end + + for _,fname in ipairs(opts.file) do + local sig = rspamd_crypto.sign_file(kp, fname) + + if not sig then + parser:error(string.format("cannot sign %s\n", fname)) + end + + local out = string.format('%s.%s', fname, opts.suffix or 'sig') + local of = io.open(out, 'w') + if not of then + parser:error('cannot open output to write: ' .. out) + end + of:write(sig:bin()) + of:close() + io.write(string.format('signed %s -> %s (%s)\n', fname, out, sig:hex())) + end else parser:error('command %s is not yet implemented', command) end -- 2.39.5