Mercurial > hgrepos > Python > apps > py-cutils
comparison shasum.py @ 7:47b4c98e4d40
Allow algorithm selection for all algorithms in :mod:`hashlib`.
Besides of the name "shasum" the MD5, BLAKE2b, BLAKE2s and SHA-3 variants
are implemented.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Fri, 04 Dec 2020 15:16:20 +0100 |
| parents | a21e83c855cc |
| children | 048b97213a23 |
comparison
equal
deleted
inserted
replaced
| 6:a21e83c855cc | 7:47b4c98e4d40 |
|---|---|
| 25 def main(argv=None): | 25 def main(argv=None): |
| 26 aparser = argparse.ArgumentParser( | 26 aparser = argparse.ArgumentParser( |
| 27 description="Python implementation of shasum", | 27 description="Python implementation of shasum", |
| 28 fromfile_prefix_chars='@') | 28 fromfile_prefix_chars='@') |
| 29 aparser.add_argument( | 29 aparser.add_argument( |
| 30 "--algorithm", "-a", action="store", type=argv2algo, | |
| 31 help="1, 224, 256 (default), 384, 512, 3-224, 3-256, 3-384, 3-512, blake2b, blake2s, md5") | |
| 32 aparser.add_argument( | |
| 30 "--binary", "-b", action="store_false", dest="text_mode", default=False, | 33 "--binary", "-b", action="store_false", dest="text_mode", default=False, |
| 31 help="read in binary mode (default)") | 34 help="read in binary mode (default)") |
| 32 aparser.add_argument( | 35 aparser.add_argument( |
| 33 "--bsd", "-B", action="store_true", | 36 "--bsd", "-B", action="store_true", |
| 34 help="write BSD style output") | 37 help="write BSD style output") |
| 42 | 45 |
| 43 if opts.text_mode: | 46 if opts.text_mode: |
| 44 print("ERROR: text mode not supported", file=sys.stderr) | 47 print("ERROR: text mode not supported", file=sys.stderr) |
| 45 sys.exit(78) # :manpage:`sysexits(3)` EX_CONFIG | 48 sys.exit(78) # :manpage:`sysexits(3)` EX_CONFIG |
| 46 | 49 |
| 50 if not opts.algorithm: | |
| 51 opts.algorithm = argv2algo("256") | |
| 52 | |
| 47 if opts.bsd: | 53 if opts.bsd: |
| 48 out = out_bsd | 54 out = out_bsd |
| 49 else: | 55 else: |
| 50 out = out_std | 56 out = out_std |
| 51 | 57 |
| 58 msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) | 64 msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) |
| 59 source = sys.stdin | 65 source = sys.stdin |
| 60 else: | 66 else: |
| 61 source = sys.stdin.buffer | 67 source = sys.stdin.buffer |
| 62 out(sys.stdout, | 68 out(sys.stdout, |
| 63 compute_digest(hashlib.sha256, source), | 69 compute_digest(opts.algorithm[0], source), |
| 64 None, | 70 None, |
| 65 "SHA256", | 71 opts.algorithm[1], |
| 66 True) | 72 True) |
| 67 else: | 73 else: |
| 68 for fn in opts.files: | 74 for fn in opts.files: |
| 69 with open(fn, "rb") as source: | 75 with open(fn, "rb") as source: |
| 70 out(sys.stdout, | 76 out(sys.stdout, |
| 71 compute_digest(hashlib.sha256, source), | 77 compute_digest(opts.algorithm[0], source), |
| 72 fn, | 78 fn, |
| 73 "SHA256", | 79 opts.algorithm[1], |
| 74 True) | 80 True) |
| 81 | |
| 82 | |
| 83 def argv2algo(s): | |
| 84 """Convert a commane line algorithm specifier into a tuple with the | |
| 85 type/factory of the digest and the algorithms tag for output purposes | |
| 86 | |
| 87 :param str s: the specifier from the commane line | |
| 88 :return: the internal digest specification | |
| 89 :rtype: a tuple (digest_type_or_factory, name_in_output) | |
| 90 | |
| 91 String comparisons are done case-insensitively. | |
| 92 | |
| 93 """ | |
| 94 s = s.lower() | |
| 95 if s in ("1", "sha1"): | |
| 96 return (hashlib.sha1, "SHA1") | |
| 97 elif s in ("224", "sha224"): | |
| 98 return (hashlib.sha224, "SHA224") | |
| 99 elif s in ("256", "sha256"): | |
| 100 return (hashlib.sha256, "SHA256") | |
| 101 elif s in ("384", "sha384"): | |
| 102 return (hashlib.sha384, "SHA384") | |
| 103 elif s in ("512", "sha512"): | |
| 104 return (hashlib.sha512, "SHA512") | |
| 105 elif s in ("3-224", "sha3-224"): | |
| 106 return (hashlib.sha3_224, "SHA3-224") | |
| 107 elif s in ("3-256", "sha3-256"): | |
| 108 return (hashlib.sha3_256, "SHA3-256") | |
| 109 elif s in ("3-384", "sha3-384"): | |
| 110 return (hashlib.sha3_384, "SHA3-384") | |
| 111 elif s in ("3-512", "sha3-512"): | |
| 112 return (hashlib.sha3_512, "SHA3-512") | |
| 113 elif s in ("blake2b", "blake2b-512"): | |
| 114 return (hashlib.blake2b, "BLAKE2b") | |
| 115 elif s in ("blake2s", "blake2s-256"): | |
| 116 return (hashlib.blake2s, "BLAKE2s") | |
| 117 elif s == "md5": | |
| 118 return (hashlib.md5, "MD5") | |
| 119 else: | |
| 120 raise argparse.ArgumentTypeError( | |
| 121 "`{}' is not a recognized algorithm".format(s)) | |
| 75 | 122 |
| 76 | 123 |
| 77 def out_bsd(dest, digest, filename, digestname, binary): | 124 def out_bsd(dest, digest, filename, digestname, binary): |
| 78 if filename is None: | 125 if filename is None: |
| 79 print(digest, file=dest) | 126 print(digest, file=dest) |
