From 77058babc6e3d0f5d4f4ec43431b7046bb8c5229 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Tue, 30 May 2017 12:40:19 +0200 Subject: [PATCH] allow passing salt to crypto.py on the command line Nifty shortcut for hashing without a corresponding pdtcrypt file. --- deltatar/crypto.py | 63 +++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 45 insertions(+), 18 deletions(-) diff --git a/deltatar/crypto.py b/deltatar/crypto.py index e49574f..5841830 100755 --- a/deltatar/crypto.py +++ b/deltatar/crypto.py @@ -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 == "-": -- 1.7.1