Gentoo Archives: gentoo-portage-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-portage-dev@l.g.o
Cc: "Michał Górny" <mgorny@g.o>
Subject: [gentoo-portage-dev] [PATCH 10/14] portage.checksum: Reorder to avoid loading redundant impls
Date: Sun, 12 Mar 2017 19:04:13
Message-Id: 20170312190011.3234-11-mgorny@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCHES] portage.checksum hacking, pt. 4 by "Michał Górny"
1 Reorder the checksum implementations to start with the most preferred
2 implementation, and try fallbacks only if the most preferred
3 implementation is not available. Most importantly, this means that
4 Portage will no longer attempt to load all hash libraries in the system,
5 especially when it can satisfy its requirements with hashlib.
6 ---
7 pym/portage/checksum.py | 145 +++++++++++++++++++++++++++++-------------------
8 1 file changed, 87 insertions(+), 58 deletions(-)
9
10 diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
11 index 659012cdc..2c482f5e7 100644
12 --- a/pym/portage/checksum.py
13 +++ b/pym/portage/checksum.py
14 @@ -93,66 +93,11 @@ class _generate_hash_function(object):
15
16 return (checksum.hexdigest(), size)
17
18 -# Define hash functions, try to use the best module available. Later definitions
19 -# override earlier ones
20
21 -# Try to use mhash if available
22 -# mhash causes GIL presently, so it gets less priority than hashlib and
23 -# pycrypto. However, it might be the only accelerated implementation of
24 -# WHIRLPOOL available.
25 -try:
26 - import mhash
27 - for local_name, hash_name in (("RMD160", "RIPEMD160"), ("WHIRLPOOL", "WHIRLPOOL")):
28 - if hasattr(mhash, 'MHASH_%s' % hash_name):
29 - _generate_hash_function(local_name,
30 - functools.partial(mhash.MHASH, getattr(mhash, 'MHASH_%s' % hash_name)),
31 - origin='mhash')
32 -except ImportError:
33 - pass
34 -
35 -# Use pycrypto when available, prefer it over the internal fallbacks
36 -# Check for 'new' attributes, since they can be missing if the module
37 -# is broken somehow.
38 -try:
39 - from Crypto.Hash import RIPEMD
40 - rmd160hash_ = getattr(RIPEMD, 'new', None)
41 - if rmd160hash_ is not None:
42 - _generate_hash_function("RMD160",
43 - rmd160hash_, origin="pycrypto")
44 -except ImportError:
45 - pass
46 -
47 -try:
48 - # added in pycryptodome
49 - from Crypto.Hash import BLAKE2b, BLAKE2s, SHA3_256, SHA3_512
50 -
51 - blake2bhash_ = getattr(BLAKE2b, 'new', None)
52 - if blake2bhash_ is not None:
53 - _generate_hash_function("BLAKE2B",
54 - functools.partial(blake2bhash_, digest_bytes=64), origin="pycrypto")
55 - blake2shash_ = getattr(BLAKE2s, 'new', None)
56 - if blake2shash_ is not None:
57 - _generate_hash_function("BLAKE2S",
58 - functools.partial(blake2shash_, digest_bytes=32), origin="pycrypto")
59 - sha3_256hash_ = getattr(SHA3_256, 'new', None)
60 - if sha3_256hash_ is not None:
61 - _generate_hash_function("SHA3_256",
62 - sha3_256hash_, origin="pycrypto")
63 - sha3_512hash_ = getattr(SHA3_512, 'new', None)
64 - if sha3_512hash_ is not None:
65 - _generate_hash_function("SHA3_512",
66 - sha3_512hash_, origin="pycrypto")
67 -except ImportError:
68 - pass
69 -
70 -# Support using pysha3 as fallback for python<3.6
71 -try:
72 - import sha3
73 +# Define hash functions, try to use the best module available. Preferred
74 +# modules should go first, latter ones should check if the hashes aren't
75 +# already defined.
76
77 - _generate_hash_function("SHA3_256", sha3.sha3_256, origin="pysha3")
78 - _generate_hash_function("SHA3_512", sha3.sha3_512, origin="pysha3")
79 -except ImportError:
80 - pass
81
82 # Use hashlib from python-2.5 if available and prefer it over pycrypto and internal fallbacks.
83 # Need special handling for RMD160/WHIRLPOOL as they may not always be provided by hashlib.
84 @@ -178,6 +123,89 @@ for local_name, hash_name in (
85 functools.partial(hashlib.new, hash_name),
86 origin='hashlib')
87
88 +
89 +# Support using pysha3 as fallback for python<3.6
90 +if "SHA3_256" not in hashfunc_map or "SHA3_512" not in hashfunc_map:
91 + try:
92 + import sha3
93 +
94 + _generate_hash_function("SHA3_256", sha3.sha3_256, origin="pysha3")
95 + _generate_hash_function("SHA3_512", sha3.sha3_512, origin="pysha3")
96 + except ImportError:
97 + pass
98 +
99 +
100 +# Use pycrypto when available, prefer it over the internal fallbacks
101 +# Check for 'new' attributes, since they can be missing if the module
102 +# is broken somehow.
103 +if 'RMD160' not in hashfunc_map:
104 + try:
105 + from Crypto.Hash import RIPEMD
106 + rmd160hash_ = getattr(RIPEMD, 'new', None)
107 + if rmd160hash_ is not None:
108 + _generate_hash_function("RMD160",
109 + rmd160hash_, origin="pycrypto")
110 + except ImportError:
111 + pass
112 +
113 +# The following hashes were added in pycryptodome (pycrypto fork)
114 +if 'BLAKE2B' not in hashfunc_map:
115 + try:
116 + from Crypto.Hash import BLAKE2b
117 + blake2bhash_ = getattr(BLAKE2b, 'new', None)
118 + if blake2bhash_ is not None:
119 + _generate_hash_function("BLAKE2B",
120 + functools.partial(blake2bhash_, digest_bytes=64), origin="pycrypto")
121 + except ImportError:
122 + pass
123 +
124 +if 'BLAKE2S' not in hashfunc_map:
125 + try:
126 + from Crypto.Hash import BLAKE2s
127 + blake2shash_ = getattr(BLAKE2s, 'new', None)
128 + if blake2shash_ is not None:
129 + _generate_hash_function("BLAKE2S",
130 + functools.partial(blake2shash_, digest_bytes=32), origin="pycrypto")
131 + except ImportError:
132 + pass
133 +
134 +if 'SHA3_256' not in hashfunc_map:
135 + try:
136 + from Crypto.Hash import SHA3_256
137 + sha3_256hash_ = getattr(SHA3_256, 'new', None)
138 + if sha3_256hash_ is not None:
139 + _generate_hash_function("SHA3_256",
140 + sha3_256hash_, origin="pycrypto")
141 + except ImportError:
142 + pass
143 +
144 +if 'SHA3_512' not in hashfunc_map:
145 + try:
146 + from Crypto.Hash import SHA3_512
147 + sha3_512hash_ = getattr(SHA3_512, 'new', None)
148 + if sha3_512hash_ is not None:
149 + _generate_hash_function("SHA3_512",
150 + sha3_512hash_, origin="pycrypto")
151 + except ImportError:
152 + pass
153 +
154 +
155 +# Try to use mhash if available
156 +# mhash causes GIL presently, so it gets less priority than hashlib and
157 +# pycrypto. However, it might be the only accelerated implementation of
158 +# WHIRLPOOL available.
159 +if 'RMD160' not in hashfunc_map or 'WHIRLPOOL' not in hashfunc_map:
160 + try:
161 + import mhash
162 + for local_name, hash_name in (("RMD160", "RIPEMD160"), ("WHIRLPOOL", "WHIRLPOOL")):
163 + if local_name not in hashfunc_map and hasattr(mhash, 'MHASH_%s' % hash_name):
164 + _generate_hash_function(local_name,
165 + functools.partial(mhash.MHASH, getattr(mhash, 'MHASH_%s' % hash_name)),
166 + origin='mhash')
167 + except ImportError:
168 + pass
169 +
170 +
171 _whirlpool_unaccelerated = False
172 if "WHIRLPOOL" not in hashfunc_map:
173 # Bundled WHIRLPOOL implementation
174 @@ -196,6 +224,7 @@ hashfunc_map["size"] = SizeHash()
175
176 # end actual hash functions
177
178 +
179 prelink_capable = False
180 if os.path.exists(PRELINK_BINARY):
181 cmd = [PRELINK_BINARY, "--version"]
182 --
183 2.12.0