allow passing salt to crypto.py on the command line
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Tue, 30 May 2017 10:40:19 +0000 (12:40 +0200)
committerThomas Jarosch <thomas.jarosch@intra2net.com>
Mon, 2 Apr 2018 11:34:09 +0000 (13:34 +0200)
Nifty shortcut for hashing without a corresponding pdtcrypt file.

deltatar/crypto.py

index e49574f..5841830 100755 (executable)
@@ -1230,6 +1230,9 @@ PDTCRYPT_SINK      = 0
 PDTCRYPT_SOURCE    = 1
 SELF               = None
 
+PDTCRYPT_DEFAULT_VER  = 1
+PDTCRYPT_DEFAULT_PVER = 1
+
 
 class PDTDecryptionError (Exception):
     """Decryption failed."""
@@ -1309,9 +1312,9 @@ def depdtcrypt (mode, secret, ins, outs):
             if outfile is None:
                 if PDTCRYPT_VERBOSE is True:
                     noise ("PDT: no output file to close at this point")
-            else:
-                if PDTCRYPT_VERBOSE is True:
-                    noise ("PDT: release output file %r" % outfile)
+                else:
+                    if PDTCRYPT_VERBOSE is True:
+                        noise ("PDT: release output file %r" % outfile)
                     # cleanup happens automatically by the GC; the next
                     # line will error out on account of an invalid fd
                     #outfile.close ()
@@ -1489,10 +1492,20 @@ def mode_depdtcrypt (mode, secret, ins, outs):
     return 0
 
 
-def mode_scrypt (pw, ins):
-    hsh, nacl, version, paramversion = scrypt_hashsource (pw, ins)
-    defs = ENCRYPTION_PARAMETERS.get(paramversion, None)
-    _kdfname, params = defs ["kdf"]
+def mode_scrypt (pw, ins=None, nacl=None):
+    hsh = None
+    if ins is not None:
+        hsh, nacl, version, paramversion = scrypt_hashsource (pw, ins)
+        defs = ENCRYPTION_PARAMETERS.get(paramversion, None)
+    else:
+        nacl    = binascii.unhexlify (nacl)
+        defs    = ENCRYPTION_PARAMETERS.get(PDTCRYPT_DEFAULT_PVER, None)
+        version = PDTCRYPT_DEFAULT_VER
+
+    kdfname, params = defs ["kdf"]
+    if hsh is None:
+        kdf = kdf_by_version (None, defs)
+        hsh, _void = kdf (pw, nacl)
 
     import json
     out = json.dumps ({ "salt"          : binascii.hexlify (nacl).decode ()
@@ -1512,9 +1525,10 @@ def usage (err=False):
     indent = ' ' * len (SELF)
     out ("usage: %s SUBCOMMAND { --help" % SELF)
     out ("       %s            | [ -v ] { -p PASSWORD | -k KEY }" % indent)
-    out ("       %s              { { -i | --in }  { - | SOURCE } }" % indent)
-    out ("       %s              { { -o | --out } { - | DESTINATION } }" % indent)
-    out ("       %s              { -D | --no-decrypt } { -S | --split }" % indent)
+    out ("       %s              [ { -i | --in }  { - | SOURCE } ]" % indent)
+    out ("       %s              [ { -n | --nacl } { SALT } ]" % indent)
+    out ("       %s              [ { -o | --out } { - | DESTINATION } ]" % indent)
+    out ("       %s              [ -D | --no-decrypt ] [ -S | --split ]" % indent)
     out ("")
     out ("\twhere")
     out ("\t\tSUBCOMMAND      main mode: { process | scrypt }")
@@ -1526,6 +1540,7 @@ def usage (err=False):
     out ("\t\t-s              enforce strict handling of initialization vectors")
     out ("\t\t-i SOURCE       file name to read from")
     out ("\t\t-o DESTINATION  file to write output to")
+    out ("\t\t-n SALT         provide salt for scrypt mode in hex encoding")
     out ("\t\t-v              print extra info")
     out ("\t\t-S              split into files at object boundaries; this")
     out ("\t\t                requires DESTINATION to refer to directory")
@@ -1549,6 +1564,7 @@ def parse_argv (argv):
     secret    = None
     insspec   = None
     outsspec  = None
+    nacl      = None
 
     argvi = iter (argv)
     SELF  = os.path.basename (next (argvi))
@@ -1585,9 +1601,6 @@ def parse_argv (argv):
         elif arg in [ "-i", "--in", "--source" ]:
             insspec = checked_arg ()
             if PDTCRYPT_VERBOSE is True: noise ("PDT: decrypt from %s" % insspec)
-        elif arg in [ "-o", "--out", "--dest", "--sink" ]:
-            outsspec = checked_arg ()
-            if PDTCRYPT_VERBOSE is True: noise ("PDT: decrypt to %s" % outsspec)
         elif arg in [ "-p", "--password" ]:
             arg = checked_arg ()
             checked_secret (PDTCRYPT_SECRET_PW, arg)
@@ -1597,6 +1610,9 @@ def parse_argv (argv):
                 if arg in [ "-s", "--strict-ivs" ]:
                     global PDTCRYPT_STRICTIVS
                     PDTCRYPT_STRICTIVS = True
+                elif arg in [ "-o", "--out", "--dest", "--sink" ]:
+                    outsspec = checked_arg ()
+                    if PDTCRYPT_VERBOSE is True: noise ("PDT: decrypt to %s" % outsspec)
                 elif arg in [ "-f", "--force" ]:
                     global PDTCRYPT_OVERWRITE
                     PDTCRYPT_OVERWRITE = True
@@ -1614,7 +1630,11 @@ def parse_argv (argv):
                 else:
                     bail ("ERROR: unexpected positional argument “%s”" % arg)
             elif subcommand == PDTCRYPT_SUB_SCRYPT:
-                bail ("ERROR: unexpected positional argument “%s”" % arg)
+                if arg in [ "-n", "--nacl", "--salt" ]:
+                    nacl = checked_arg ()
+                    if PDTCRYPT_VERBOSE is True: noise ("PDT: salt key with %s" % nacl)
+                else:
+                    bail ("ERROR: unexpected positional argument “%s”" % arg)
 
     if secret is None:
         if PDTCRYPT_VERBOSE is True:
@@ -1636,14 +1656,21 @@ def parse_argv (argv):
         elif mode & PDTCRYPT_DECRYPT:
             bail ("ERROR: encryption requested but no password given")
 
-    if subcommand == PDTCRYPT_SUB_SCRYPT and secret [0] == PDTCRYPT_SECRET_KEY:
-        bail ("ERROR: scrypt mode requires a password")
+    if subcommand == PDTCRYPT_SUB_SCRYPT:
+        if secret [0] == PDTCRYPT_SECRET_KEY:
+            bail ("ERROR: scrypt mode requires a password")
+        if     insspec is not None and nacl is not None \
+            or insspec is     None and nacl is     None :
+                bail ("ERROR: please supply either an input file or "
+                      "the salt")
 
     # default to stdout
-    ins = deptdcrypt_mk_stream (PDTCRYPT_SOURCE, insspec  or "-")
+    ins = None
+    if insspec is not None or subcommand != PDTCRYPT_SUB_SCRYPT:
+        ins = deptdcrypt_mk_stream (PDTCRYPT_SOURCE, insspec or "-")
 
     if subcommand == PDTCRYPT_SUB_SCRYPT:
-        return True, partial (mode_scrypt, secret [1].encode (), ins)
+        return True, partial (mode_scrypt, secret [1].encode (), ins, nacl)
 
     if mode & PDTCRYPT_SPLIT: # destination must be directory
         if outsspec is None or outsspec == "-":