comparison cutils/util/__init__.py @ 118:12339ac2148d

Move some functions into cutils.util (i.e. algorithms and their aliases)
author Franz Glasner <fzglas.hg@dom66.de>
date Sun, 29 Dec 2024 18:22:22 +0100
parents e15b3d1ff0d9
children a548783381b6
comparison
equal deleted inserted replaced
117:e51f34ad6d71 118:12339ac2148d
5 # :- 5 # :-
6 r"""Utility package. 6 r"""Utility package.
7 7
8 """ 8 """
9 9
10 __all__ = [] 10 __all__ = ["normalize_filename",
11 "argv2algo",
12 "algotag2algotype",
13 "get_blake2b",
14 "get_blake2b_256",
15 "get_blake2s",
16 ]
17
18
19 import argparse
20 import hashlib
21
22
23 def get_blake2b():
24 """Get the factory for blake2b"""
25 try:
26 return hashlib.blake2b
27 except AttributeError:
28 import pyblake2
29 return pyblake2.blake2b
30
31
32 def get_blake2b_256():
33 """Get the factory for blake2b-256"""
34
35 try:
36 hashlib.blake2b
37 except AttributeError:
38 import pyblake2
39
40 def _get_blake():
41 return pyblake2.blake2b(digest_size=32)
42
43 else:
44
45 def _get_blake():
46 return hashlib.blake2b(digest_size=32)
47
48 return _get_blake
49
50
51 def get_blake2s():
52 """Get the factory for blake2s"""
53 try:
54 return hashlib.blake2s
55 except AttributeError:
56 import pyblake2
57 return pyblake2.blake2s
58
59
60 def argv2algo(s):
61 """Convert a command line algorithm specifier into a tuple with the
62 type/factory of the digest and the algorithms tag for output purposes.
63
64 :param str s: the specifier from the commane line
65 :return: the internal digest specification
66 :rtype: a tuple (digest_type_or_factory, name_in_output)
67 :raises argparse.ArgumentTypeError: for unrecognized algorithms or names
68
69 String comparisons are done case-insensitively.
70
71 """
72 s = s.lower()
73 if s in ("1", "sha1"):
74 return (hashlib.sha1, "SHA1")
75 elif s in ("224", "sha224"):
76 return (hashlib.sha224, "SHA224")
77 elif s in ("256", "sha256"):
78 return (hashlib.sha256, "SHA256")
79 elif s in ("384", "sha384"):
80 return (hashlib.sha384, "SHA384")
81 elif s in ("512", "sha512"):
82 return (hashlib.sha512, "SHA512")
83 elif s in ("3-224", "sha3-224"):
84 return (hashlib.sha3_224, "SHA3-224")
85 elif s in ("3-256", "sha3-256"):
86 return (hashlib.sha3_256, "SHA3-256")
87 elif s in ("3-384", "sha3-384"):
88 return (hashlib.sha3_384, "SHA3-384")
89 elif s in ("3-512", "sha3-512"):
90 return (hashlib.sha3_512, "SHA3-512")
91 elif s in ("blake2b", "blake2b-512", "blake2", "blake2-512"):
92 return (get_blake2b(), "BLAKE2b")
93 elif s in ("blake2s", "blake2s-256"):
94 return (get_blake2s(), "BLAKE2s")
95 elif s in ("blake2-256", "blake2b-256"):
96 return (get_blake2b_256(), "BLAKE2b-256")
97 elif s == "md5":
98 return (hashlib.md5, "MD5")
99 else:
100 raise argparse.ArgumentTypeError(
101 "`{}' is not a recognized algorithm".format(s))
102
103
104 def algotag2algotype(s):
105 """Convert the algorithm specifier in a BSD-style digest file to the
106 type/factory of the corresponding algorithm.
107
108 :param str s: the tag (i.e. normalized name) or the algorithm
109 :return: the digest type or factory for `s`
110 :raises ValueError: on unknown and/or unhandled algorithms
111
112 All string comparisons are case-sensitive.
113
114 """
115 if s == "SHA1":
116 return hashlib.sha1
117 elif s == "SHA224":
118 return hashlib.sha224
119 elif s == "SHA256":
120 return hashlib.sha256
121 elif s == "SHA384":
122 return hashlib.sha384
123 elif s == "SHA512":
124 return hashlib.sha512
125 elif s == "SHA3-224":
126 return hashlib.sha3_224
127 elif s == "SHA3-256":
128 return hashlib.sha3_256
129 elif s == "SHA3-384":
130 return hashlib.sha3_384
131 elif s == "SHA3-512":
132 return hashlib.sha3_512
133 elif s in ("BLAKE2b", "BLAKE2b-512", "BLAKE2b512"): # compat for openssl
134 return get_blake2b()
135 elif s in ("BLAKE2s", "BLAKE2s-256", "BLAKE2s256"): # compat for openssl
136 return get_blake2s()
137 elif s in ("BLAKE2b-256", "BLAKE2b256"): # also compat for openssl dgst
138 return get_blake2b_256()
139 elif s == "MD5":
140 return hashlib.md5
141 else:
142 raise ValueError("unknown algorithm: {}".format(s))
143
144
145 def normalize_filename(filename, strip_leading_dot_slash=False):
146 filename = filename.replace("\\", "/")
147 if strip_leading_dot_slash:
148 while filename.startswith("./"):
149 filename = filename[2:]
150 return filename