bpo-31664: Add support for the Blowfish method in crypt. (#3854)

This commit is contained in:
Serhiy Storchaka 2017-10-24 19:36:17 +03:00 committed by GitHub
parent 831d61d56c
commit eab3ff72eb
5 changed files with 104 additions and 31 deletions

View file

@ -19,7 +19,7 @@ class _Method(_namedtuple('_Method', 'name ident salt_chars total_size')):
return '<crypt.METHOD_{}>'.format(self.name)
def mksalt(method=None):
def mksalt(method=None, *, log_rounds=12):
"""Generate a salt for the specified method.
If not specified, the strongest available method will be used.
@ -27,7 +27,12 @@ def mksalt(method=None):
"""
if method is None:
method = methods[0]
s = '${}$'.format(method.ident) if method.ident else ''
if not method.ident:
s = ''
elif method.ident[0] == '2':
s = f'${method.ident}${log_rounds:02d}$'
else:
s = f'${method.ident}$'
s += ''.join(_sr.choice(_saltchars) for char in range(method.salt_chars))
return s
@ -48,14 +53,31 @@ def crypt(word, salt=None):
# available salting/crypto methods
METHOD_CRYPT = _Method('CRYPT', None, 2, 13)
METHOD_MD5 = _Method('MD5', '1', 8, 34)
METHOD_SHA256 = _Method('SHA256', '5', 16, 63)
METHOD_SHA512 = _Method('SHA512', '6', 16, 106)
methods = []
for _method in (METHOD_SHA512, METHOD_SHA256, METHOD_MD5, METHOD_CRYPT):
_result = crypt('', _method)
if _result and len(_result) == _method.total_size:
methods.append(_method)
del _result, _method
def _add_method(name, *args):
method = _Method(name, *args)
globals()['METHOD_' + name] = method
salt = mksalt(method, log_rounds=4)
result = crypt('', salt)
if result and len(result) == method.total_size:
methods.append(method)
return True
return False
_add_method('SHA512', '6', 16, 106)
_add_method('SHA256', '5', 16, 63)
# Choose the strongest supported version of Blowfish hashing.
# Early versions have flaws. Version 'a' fixes flaws of
# the initial implementation, 'b' fixes flaws of 'a'.
# 'y' is the same as 'b', for compatibility
# with openwall crypt_blowfish.
for _v in 'b', 'y', 'a', '':
if _add_method('BLOWFISH', '2' + _v, 22, 59 + len(_v)):
break
_add_method('MD5', '1', 8, 34)
_add_method('CRYPT', None, 2, 13)
del _v, _add_method