From b360b772498d84090b19df9b90adea798e5d6874 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Thu, 11 May 2017 10:50:30 +0200 Subject: [PATCH] export scrypt hashing functionality --- deltatar/crypto.py | 89 ++++++++++++++++++++++++++++++++------------------- 1 files changed, 56 insertions(+), 33 deletions(-) diff --git a/deltatar/crypto.py b/deltatar/crypto.py index e4a121a..f2dd19c 100755 --- a/deltatar/crypto.py +++ b/deltatar/crypto.py @@ -90,6 +90,7 @@ import cryptography __all__ = [ "hdr_make", "hdr_read", "hdr_fmt", "hdr_fmt_pretty" + , "scrypt_hashfile" , "PDTCRYPT_HDR_SIZE", "AES_GCM_IV_CNT_DATA" , "AES_GCM_IV_CNT_INFOFILE", "AES_GCM_IV_CNT_INDEX" ] @@ -440,6 +441,57 @@ def kdf_by_version (paramversion=None, defs=None): return partial (fn, params) +############################################################################### +## SCRYPT hashing +############################################################################### + +def scrypt_hashsource (pw, ins): + """ + Calculate the SCRYPT hash from the password and the information contained + in the first header found in ``ins``. + + This does not validate whether the first object is encrypted correctly. + """ + hdr = None + try: + hdr = hdr_read_stream (ins) + except EndOfFile as exn: + noise ("PDT: malformed input: end of file reading first object header") + noise ("PDT:") + return 1 + + nacl = hdr ["nacl"] + pver = hdr ["paramversion"] + if PDTCRYPT_VERBOSE is True: + noise ("PDT: salt of first object : %s" % binascii.hexlify (nacl)) + noise ("PDT: parameter version of archive : %d" % pver) + + try: + defs = ENCRYPTION_PARAMETERS.get(pver, None) + kdfname, params = defs ["kdf"] + if kdfname != "scrypt": + noise ("PDT: input is not an SCRYPT archive") + noise ("") + return 1 + kdf = kdf_by_version (None, defs) + except ValueError as exn: + noise ("PDT: object has unknown parameter version %d" % pver) + + hsh, _void = kdf (pw, nacl) + + return hsh, nacl, params + + +def scrypt_hashfile (pw, fname): + with deptdcrypt_mk_stream (PDTCRYPT_SOURCE, fname or "-") as ins: + hsh, _void, _void = scrypt_hashsource (pw, ins) + return hsh + + +############################################################################### +## AES-GCM context +############################################################################### + class Crypto (object): """ Encryption context to remain alive throughout an entire tarfile pass. @@ -1129,34 +1181,7 @@ def mode_depdtcrypt (mode, pw, ins, outs): def mode_scrypt (pw, ins): - hdr = None - try: - hdr = hdr_read_stream (ins) - except EndOfFile as exn: - noise ("PDT: malformed input: end of file reading first object header") - noise ("PDT:") - return 1 - finally: - ins.close () - - nacl = hdr ["nacl"] - pver = hdr ["paramversion"] - if PDTCRYPT_VERBOSE is True: - noise ("PDT: salt of first object : %s" % binascii.hexlify (nacl)) - noise ("PDT: parameter version of archive : %d" % pver) - - try: - defs = ENCRYPTION_PARAMETERS.get(pver, None) - kdfname, params = defs ["kdf"] - if kdfname != "scrypt": - noise ("PDT: input is not an SCRYPT archive") - noise ("") - return 1 - kdf = kdf_by_version (None, defs) - except ValueError as exn: - noise ("PDT: object has unknown parameter version %d" % pver) - - hsh, _void = kdf (pw, nacl) + hsh, nacl, params = scrypt_hashsource (pw, ins) import json out = json.dumps ({ "salt" : str (binascii.hexlify (nacl)) @@ -1266,9 +1291,7 @@ def parse_argv (argv): else: raise Unreachable - if pw is not None: - pw = pw.encode () - else: + if pw is None: if subcommand == PDTCRYPT_SUB_SCRYPT: noise ("ERROR: scrypt hash mode requested but no password given") noise ("") @@ -1281,10 +1304,10 @@ def parse_argv (argv): raise Unreachable # default to stdout - ins = deptdcrypt_mk_stream (PDTCRYPT_SOURCE, insspec or "-") + ins = deptdcrypt_mk_stream (PDTCRYPT_SOURCE, insspec or "-") if subcommand == PDTCRYPT_SUB_SCRYPT: - return True, partial (mode_scrypt, pw, ins) + return True, partial (mode_scrypt, pw.encode (), ins) if mode & PDTCRYPT_SPLIT: # destination must be directory if outsspec is None or outsspec == "-": -- 1.7.1