]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Implement signing using `rspamadm keypair`
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 3 Jun 2018 20:54:00 +0000 (21:54 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 3 Jun 2018 20:54:00 +0000 (21:54 +0100)
lualib/rspamadm/keypair.lua

index b5155dfaa7c8e7f270512f094d3085b0d992c387..69b50b921333ef1bf3072011ca11726140c509c6 100644 (file)
@@ -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 "<file>"
 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 "<file>"
+sign:option "-s --suffix"
+    :description "Suffix for signature"
+    :argname "<suffix>"
+    :default("sig")
+sign:argument "file"
+    :description "File to sign"
+    :argname "<file>"
+    :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 "<file>"
 
 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