mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Initial commit
This commit is contained in:
607
venv/Lib/site-packages/passlib/handlers/des_crypt.py
Normal file
607
venv/Lib/site-packages/passlib/handlers/des_crypt.py
Normal file
@@ -0,0 +1,607 @@
|
||||
"""passlib.handlers.des_crypt - traditional unix (DES) crypt and variants"""
|
||||
#=============================================================================
|
||||
# imports
|
||||
#=============================================================================
|
||||
# core
|
||||
import re
|
||||
import logging; log = logging.getLogger(__name__)
|
||||
from warnings import warn
|
||||
# site
|
||||
# pkg
|
||||
from passlib.utils import safe_crypt, test_crypt, to_unicode
|
||||
from passlib.utils.binary import h64, h64big
|
||||
from passlib.utils.compat import byte_elem_value, u, uascii_to_str, unicode, suppress_cause
|
||||
from passlib.crypto.des import des_encrypt_int_block
|
||||
import passlib.utils.handlers as uh
|
||||
# local
|
||||
__all__ = [
|
||||
"des_crypt",
|
||||
"bsdi_crypt",
|
||||
"bigcrypt",
|
||||
"crypt16",
|
||||
]
|
||||
|
||||
#=============================================================================
|
||||
# pure-python backend for des_crypt family
|
||||
#=============================================================================
|
||||
_BNULL = b'\x00'
|
||||
|
||||
def _crypt_secret_to_key(secret):
|
||||
"""convert secret to 64-bit DES key.
|
||||
|
||||
this only uses the first 8 bytes of the secret,
|
||||
and discards the high 8th bit of each byte at that.
|
||||
a null parity bit is inserted after every 7th bit of the output.
|
||||
"""
|
||||
# NOTE: this would set the parity bits correctly,
|
||||
# but des_encrypt_int_block() would just ignore them...
|
||||
##return sum(expand_7bit(byte_elem_value(c) & 0x7f) << (56-i*8)
|
||||
## for i, c in enumerate(secret[:8]))
|
||||
return sum((byte_elem_value(c) & 0x7f) << (57-i*8)
|
||||
for i, c in enumerate(secret[:8]))
|
||||
|
||||
def _raw_des_crypt(secret, salt):
|
||||
"""pure-python backed for des_crypt"""
|
||||
assert len(salt) == 2
|
||||
|
||||
# NOTE: some OSes will accept non-HASH64 characters in the salt,
|
||||
# but what value they assign these characters varies wildy,
|
||||
# so just rejecting them outright.
|
||||
# the same goes for single-character salts...
|
||||
# some OSes duplicate the char, some insert a '.' char,
|
||||
# and openbsd does (something) which creates an invalid hash.
|
||||
salt_value = h64.decode_int12(salt)
|
||||
|
||||
# gotta do something - no official policy since this predates unicode
|
||||
if isinstance(secret, unicode):
|
||||
secret = secret.encode("utf-8")
|
||||
assert isinstance(secret, bytes)
|
||||
|
||||
# forbidding NULL char because underlying crypt() rejects them too.
|
||||
if _BNULL in secret:
|
||||
raise uh.exc.NullPasswordError(des_crypt)
|
||||
|
||||
# convert first 8 bytes of secret string into an integer
|
||||
key_value = _crypt_secret_to_key(secret)
|
||||
|
||||
# run data through des using input of 0
|
||||
result = des_encrypt_int_block(key_value, 0, salt_value, 25)
|
||||
|
||||
# run h64 encode on result
|
||||
return h64big.encode_int64(result)
|
||||
|
||||
def _bsdi_secret_to_key(secret):
|
||||
"""convert secret to DES key used by bsdi_crypt"""
|
||||
key_value = _crypt_secret_to_key(secret)
|
||||
idx = 8
|
||||
end = len(secret)
|
||||
while idx < end:
|
||||
next = idx + 8
|
||||
tmp_value = _crypt_secret_to_key(secret[idx:next])
|
||||
key_value = des_encrypt_int_block(key_value, key_value) ^ tmp_value
|
||||
idx = next
|
||||
return key_value
|
||||
|
||||
def _raw_bsdi_crypt(secret, rounds, salt):
|
||||
"""pure-python backend for bsdi_crypt"""
|
||||
|
||||
# decode salt
|
||||
salt_value = h64.decode_int24(salt)
|
||||
|
||||
# gotta do something - no official policy since this predates unicode
|
||||
if isinstance(secret, unicode):
|
||||
secret = secret.encode("utf-8")
|
||||
assert isinstance(secret, bytes)
|
||||
|
||||
# forbidding NULL char because underlying crypt() rejects them too.
|
||||
if _BNULL in secret:
|
||||
raise uh.exc.NullPasswordError(bsdi_crypt)
|
||||
|
||||
# convert secret string into an integer
|
||||
key_value = _bsdi_secret_to_key(secret)
|
||||
|
||||
# run data through des using input of 0
|
||||
result = des_encrypt_int_block(key_value, 0, salt_value, rounds)
|
||||
|
||||
# run h64 encode on result
|
||||
return h64big.encode_int64(result)
|
||||
|
||||
#=============================================================================
|
||||
# handlers
|
||||
#=============================================================================
|
||||
class des_crypt(uh.TruncateMixin, uh.HasManyBackends, uh.HasSalt, uh.GenericHandler):
|
||||
"""This class implements the des-crypt password hash, and follows the :ref:`password-hash-api`.
|
||||
|
||||
It supports a fixed-length salt.
|
||||
|
||||
The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
|
||||
|
||||
:type salt: str
|
||||
:param salt:
|
||||
Optional salt string.
|
||||
If not specified, one will be autogenerated (this is recommended).
|
||||
If specified, it must be 2 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
|
||||
|
||||
:param bool truncate_error:
|
||||
By default, des_crypt will silently truncate passwords larger than 8 bytes.
|
||||
Setting ``truncate_error=True`` will cause :meth:`~passlib.ifc.PasswordHash.hash`
|
||||
to raise a :exc:`~passlib.exc.PasswordTruncateError` instead.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
:type relaxed: bool
|
||||
:param relaxed:
|
||||
By default, providing an invalid value for one of the other
|
||||
keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
|
||||
and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
|
||||
will be issued instead. Correctable errors include
|
||||
``salt`` strings that are too long.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
"""
|
||||
#===================================================================
|
||||
# class attrs
|
||||
#===================================================================
|
||||
|
||||
#--------------------
|
||||
# PasswordHash
|
||||
#--------------------
|
||||
name = "des_crypt"
|
||||
setting_kwds = ("salt", "truncate_error")
|
||||
|
||||
#--------------------
|
||||
# GenericHandler
|
||||
#--------------------
|
||||
checksum_chars = uh.HASH64_CHARS
|
||||
checksum_size = 11
|
||||
|
||||
#--------------------
|
||||
# HasSalt
|
||||
#--------------------
|
||||
min_salt_size = max_salt_size = 2
|
||||
salt_chars = uh.HASH64_CHARS
|
||||
|
||||
#--------------------
|
||||
# TruncateMixin
|
||||
#--------------------
|
||||
truncate_size = 8
|
||||
|
||||
#===================================================================
|
||||
# formatting
|
||||
#===================================================================
|
||||
# FORMAT: 2 chars of H64-encoded salt + 11 chars of H64-encoded checksum
|
||||
|
||||
_hash_regex = re.compile(u(r"""
|
||||
^
|
||||
(?P<salt>[./a-z0-9]{2})
|
||||
(?P<chk>[./a-z0-9]{11})?
|
||||
$"""), re.X|re.I)
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, hash):
|
||||
hash = to_unicode(hash, "ascii", "hash")
|
||||
salt, chk = hash[:2], hash[2:]
|
||||
return cls(salt=salt, checksum=chk or None)
|
||||
|
||||
def to_string(self):
|
||||
hash = u("%s%s") % (self.salt, self.checksum)
|
||||
return uascii_to_str(hash)
|
||||
|
||||
#===================================================================
|
||||
# digest calculation
|
||||
#===================================================================
|
||||
def _calc_checksum(self, secret):
|
||||
# check for truncation (during .hash() calls only)
|
||||
if self.use_defaults:
|
||||
self._check_truncate_policy(secret)
|
||||
|
||||
return self._calc_checksum_backend(secret)
|
||||
|
||||
#===================================================================
|
||||
# backend
|
||||
#===================================================================
|
||||
backends = ("os_crypt", "builtin")
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# os_crypt backend
|
||||
#---------------------------------------------------------------
|
||||
@classmethod
|
||||
def _load_backend_os_crypt(cls):
|
||||
if test_crypt("test", 'abgOeLfPimXQo'):
|
||||
cls._set_calc_checksum_backend(cls._calc_checksum_os_crypt)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _calc_checksum_os_crypt(self, secret):
|
||||
# NOTE: we let safe_crypt() encode unicode secret -> utf8;
|
||||
# no official policy since des-crypt predates unicode
|
||||
hash = safe_crypt(secret, self.salt)
|
||||
if hash is None:
|
||||
# py3's crypt.crypt() can't handle non-utf8 bytes.
|
||||
# fallback to builtin alg, which is always available.
|
||||
return self._calc_checksum_builtin(secret)
|
||||
if not hash.startswith(self.salt) or len(hash) != 13:
|
||||
raise uh.exc.CryptBackendError(self, self.salt, hash)
|
||||
return hash[2:]
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# builtin backend
|
||||
#---------------------------------------------------------------
|
||||
@classmethod
|
||||
def _load_backend_builtin(cls):
|
||||
cls._set_calc_checksum_backend(cls._calc_checksum_builtin)
|
||||
return True
|
||||
|
||||
def _calc_checksum_builtin(self, secret):
|
||||
return _raw_des_crypt(secret, self.salt.encode("ascii")).decode("ascii")
|
||||
|
||||
#===================================================================
|
||||
# eoc
|
||||
#===================================================================
|
||||
|
||||
class bsdi_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler):
|
||||
"""This class implements the BSDi-Crypt password hash, and follows the :ref:`password-hash-api`.
|
||||
|
||||
It supports a fixed-length salt, and a variable number of rounds.
|
||||
|
||||
The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
|
||||
|
||||
:type salt: str
|
||||
:param salt:
|
||||
Optional salt string.
|
||||
If not specified, one will be autogenerated (this is recommended).
|
||||
If specified, it must be 4 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
|
||||
|
||||
:type rounds: int
|
||||
:param rounds:
|
||||
Optional number of rounds to use.
|
||||
Defaults to 5001, must be between 1 and 16777215, inclusive.
|
||||
|
||||
:type relaxed: bool
|
||||
:param relaxed:
|
||||
By default, providing an invalid value for one of the other
|
||||
keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
|
||||
and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
|
||||
will be issued instead. Correctable errors include ``rounds``
|
||||
that are too small or too large, and ``salt`` strings that are too long.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
:meth:`hash` will now issue a warning if an even number of rounds is used
|
||||
(see :ref:`bsdi-crypt-security-issues` regarding weak DES keys).
|
||||
"""
|
||||
#===================================================================
|
||||
# class attrs
|
||||
#===================================================================
|
||||
#--GenericHandler--
|
||||
name = "bsdi_crypt"
|
||||
setting_kwds = ("salt", "rounds")
|
||||
checksum_size = 11
|
||||
checksum_chars = uh.HASH64_CHARS
|
||||
|
||||
#--HasSalt--
|
||||
min_salt_size = max_salt_size = 4
|
||||
salt_chars = uh.HASH64_CHARS
|
||||
|
||||
#--HasRounds--
|
||||
default_rounds = 5001
|
||||
min_rounds = 1
|
||||
max_rounds = 16777215 # (1<<24)-1
|
||||
rounds_cost = "linear"
|
||||
|
||||
# NOTE: OpenBSD login.conf reports 7250 as minimum allowed rounds,
|
||||
# but that seems to be an OS policy, not a algorithm limitation.
|
||||
|
||||
#===================================================================
|
||||
# parsing
|
||||
#===================================================================
|
||||
_hash_regex = re.compile(u(r"""
|
||||
^
|
||||
_
|
||||
(?P<rounds>[./a-z0-9]{4})
|
||||
(?P<salt>[./a-z0-9]{4})
|
||||
(?P<chk>[./a-z0-9]{11})?
|
||||
$"""), re.X|re.I)
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, hash):
|
||||
hash = to_unicode(hash, "ascii", "hash")
|
||||
m = cls._hash_regex.match(hash)
|
||||
if not m:
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
rounds, salt, chk = m.group("rounds", "salt", "chk")
|
||||
return cls(
|
||||
rounds=h64.decode_int24(rounds.encode("ascii")),
|
||||
salt=salt,
|
||||
checksum=chk,
|
||||
)
|
||||
|
||||
def to_string(self):
|
||||
hash = u("_%s%s%s") % (h64.encode_int24(self.rounds).decode("ascii"),
|
||||
self.salt, self.checksum)
|
||||
return uascii_to_str(hash)
|
||||
|
||||
#===================================================================
|
||||
# validation
|
||||
#===================================================================
|
||||
|
||||
# NOTE: keeping this flag for admin/choose_rounds.py script.
|
||||
# want to eventually expose rounds logic to that script in better way.
|
||||
_avoid_even_rounds = True
|
||||
|
||||
@classmethod
|
||||
def using(cls, **kwds):
|
||||
subcls = super(bsdi_crypt, cls).using(**kwds)
|
||||
if not subcls.default_rounds & 1:
|
||||
# issue warning if caller set an even 'rounds' value.
|
||||
warn("bsdi_crypt rounds should be odd, as even rounds may reveal weak DES keys",
|
||||
uh.exc.PasslibSecurityWarning)
|
||||
return subcls
|
||||
|
||||
@classmethod
|
||||
def _generate_rounds(cls):
|
||||
rounds = super(bsdi_crypt, cls)._generate_rounds()
|
||||
# ensure autogenerated rounds are always odd
|
||||
# NOTE: doing this even for default_rounds so needs_update() doesn't get
|
||||
# caught in a loop.
|
||||
# FIXME: this technically might generate a rounds value 1 larger
|
||||
# than the requested upper bound - but better to err on side of safety.
|
||||
return rounds|1
|
||||
|
||||
#===================================================================
|
||||
# migration
|
||||
#===================================================================
|
||||
|
||||
def _calc_needs_update(self, **kwds):
|
||||
# mark bsdi_crypt hashes as deprecated if they have even rounds.
|
||||
if not self.rounds & 1:
|
||||
return True
|
||||
# hand off to base implementation
|
||||
return super(bsdi_crypt, self)._calc_needs_update(**kwds)
|
||||
|
||||
#===================================================================
|
||||
# backends
|
||||
#===================================================================
|
||||
backends = ("os_crypt", "builtin")
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# os_crypt backend
|
||||
#---------------------------------------------------------------
|
||||
@classmethod
|
||||
def _load_backend_os_crypt(cls):
|
||||
if test_crypt("test", '_/...lLDAxARksGCHin.'):
|
||||
cls._set_calc_checksum_backend(cls._calc_checksum_os_crypt)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _calc_checksum_os_crypt(self, secret):
|
||||
config = self.to_string()
|
||||
hash = safe_crypt(secret, config)
|
||||
if hash is None:
|
||||
# py3's crypt.crypt() can't handle non-utf8 bytes.
|
||||
# fallback to builtin alg, which is always available.
|
||||
return self._calc_checksum_builtin(secret)
|
||||
if not hash.startswith(config[:9]) or len(hash) != 20:
|
||||
raise uh.exc.CryptBackendError(self, config, hash)
|
||||
return hash[-11:]
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# builtin backend
|
||||
#---------------------------------------------------------------
|
||||
@classmethod
|
||||
def _load_backend_builtin(cls):
|
||||
cls._set_calc_checksum_backend(cls._calc_checksum_builtin)
|
||||
return True
|
||||
|
||||
def _calc_checksum_builtin(self, secret):
|
||||
return _raw_bsdi_crypt(secret, self.rounds, self.salt.encode("ascii")).decode("ascii")
|
||||
|
||||
#===================================================================
|
||||
# eoc
|
||||
#===================================================================
|
||||
|
||||
class bigcrypt(uh.HasSalt, uh.GenericHandler):
|
||||
"""This class implements the BigCrypt password hash, and follows the :ref:`password-hash-api`.
|
||||
|
||||
It supports a fixed-length salt.
|
||||
|
||||
The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
|
||||
|
||||
:type salt: str
|
||||
:param salt:
|
||||
Optional salt string.
|
||||
If not specified, one will be autogenerated (this is recommended).
|
||||
If specified, it must be 22 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
|
||||
|
||||
:type relaxed: bool
|
||||
:param relaxed:
|
||||
By default, providing an invalid value for one of the other
|
||||
keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
|
||||
and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
|
||||
will be issued instead. Correctable errors include
|
||||
``salt`` strings that are too long.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
"""
|
||||
#===================================================================
|
||||
# class attrs
|
||||
#===================================================================
|
||||
#--GenericHandler--
|
||||
name = "bigcrypt"
|
||||
setting_kwds = ("salt",)
|
||||
checksum_chars = uh.HASH64_CHARS
|
||||
# NOTE: checksum chars must be multiple of 11
|
||||
|
||||
#--HasSalt--
|
||||
min_salt_size = max_salt_size = 2
|
||||
salt_chars = uh.HASH64_CHARS
|
||||
|
||||
#===================================================================
|
||||
# internal helpers
|
||||
#===================================================================
|
||||
_hash_regex = re.compile(u(r"""
|
||||
^
|
||||
(?P<salt>[./a-z0-9]{2})
|
||||
(?P<chk>([./a-z0-9]{11})+)?
|
||||
$"""), re.X|re.I)
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, hash):
|
||||
hash = to_unicode(hash, "ascii", "hash")
|
||||
m = cls._hash_regex.match(hash)
|
||||
if not m:
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
salt, chk = m.group("salt", "chk")
|
||||
return cls(salt=salt, checksum=chk)
|
||||
|
||||
def to_string(self):
|
||||
hash = u("%s%s") % (self.salt, self.checksum)
|
||||
return uascii_to_str(hash)
|
||||
|
||||
def _norm_checksum(self, checksum, relaxed=False):
|
||||
checksum = super(bigcrypt, self)._norm_checksum(checksum, relaxed=relaxed)
|
||||
if len(checksum) % 11:
|
||||
raise uh.exc.InvalidHashError(self)
|
||||
return checksum
|
||||
|
||||
#===================================================================
|
||||
# backend
|
||||
#===================================================================
|
||||
def _calc_checksum(self, secret):
|
||||
if isinstance(secret, unicode):
|
||||
secret = secret.encode("utf-8")
|
||||
chk = _raw_des_crypt(secret, self.salt.encode("ascii"))
|
||||
idx = 8
|
||||
end = len(secret)
|
||||
while idx < end:
|
||||
next = idx + 8
|
||||
chk += _raw_des_crypt(secret[idx:next], chk[-11:-9])
|
||||
idx = next
|
||||
return chk.decode("ascii")
|
||||
|
||||
#===================================================================
|
||||
# eoc
|
||||
#===================================================================
|
||||
|
||||
class crypt16(uh.TruncateMixin, uh.HasSalt, uh.GenericHandler):
|
||||
"""This class implements the crypt16 password hash, and follows the :ref:`password-hash-api`.
|
||||
|
||||
It supports a fixed-length salt.
|
||||
|
||||
The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
|
||||
|
||||
:type salt: str
|
||||
:param salt:
|
||||
Optional salt string.
|
||||
If not specified, one will be autogenerated (this is recommended).
|
||||
If specified, it must be 2 characters, drawn from the regexp range ``[./0-9A-Za-z]``.
|
||||
|
||||
:param bool truncate_error:
|
||||
By default, crypt16 will silently truncate passwords larger than 16 bytes.
|
||||
Setting ``truncate_error=True`` will cause :meth:`~passlib.ifc.PasswordHash.hash`
|
||||
to raise a :exc:`~passlib.exc.PasswordTruncateError` instead.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
:type relaxed: bool
|
||||
:param relaxed:
|
||||
By default, providing an invalid value for one of the other
|
||||
keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
|
||||
and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
|
||||
will be issued instead. Correctable errors include
|
||||
``salt`` strings that are too long.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
"""
|
||||
#===================================================================
|
||||
# class attrs
|
||||
#===================================================================
|
||||
|
||||
#--------------------
|
||||
# PasswordHash
|
||||
#--------------------
|
||||
name = "crypt16"
|
||||
setting_kwds = ("salt", "truncate_error")
|
||||
|
||||
#--------------------
|
||||
# GenericHandler
|
||||
#--------------------
|
||||
checksum_size = 22
|
||||
checksum_chars = uh.HASH64_CHARS
|
||||
|
||||
#--------------------
|
||||
# HasSalt
|
||||
#--------------------
|
||||
min_salt_size = max_salt_size = 2
|
||||
salt_chars = uh.HASH64_CHARS
|
||||
|
||||
#--------------------
|
||||
# TruncateMixin
|
||||
#--------------------
|
||||
truncate_size = 16
|
||||
|
||||
#===================================================================
|
||||
# internal helpers
|
||||
#===================================================================
|
||||
_hash_regex = re.compile(u(r"""
|
||||
^
|
||||
(?P<salt>[./a-z0-9]{2})
|
||||
(?P<chk>[./a-z0-9]{22})?
|
||||
$"""), re.X|re.I)
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, hash):
|
||||
hash = to_unicode(hash, "ascii", "hash")
|
||||
m = cls._hash_regex.match(hash)
|
||||
if not m:
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
salt, chk = m.group("salt", "chk")
|
||||
return cls(salt=salt, checksum=chk)
|
||||
|
||||
def to_string(self):
|
||||
hash = u("%s%s") % (self.salt, self.checksum)
|
||||
return uascii_to_str(hash)
|
||||
|
||||
#===================================================================
|
||||
# backend
|
||||
#===================================================================
|
||||
def _calc_checksum(self, secret):
|
||||
if isinstance(secret, unicode):
|
||||
secret = secret.encode("utf-8")
|
||||
|
||||
# check for truncation (during .hash() calls only)
|
||||
if self.use_defaults:
|
||||
self._check_truncate_policy(secret)
|
||||
|
||||
# parse salt value
|
||||
try:
|
||||
salt_value = h64.decode_int12(self.salt.encode("ascii"))
|
||||
except ValueError: # pragma: no cover - caught by class
|
||||
raise suppress_cause(ValueError("invalid chars in salt"))
|
||||
|
||||
# convert first 8 byts of secret string into an integer,
|
||||
key1 = _crypt_secret_to_key(secret)
|
||||
|
||||
# run data through des using input of 0
|
||||
result1 = des_encrypt_int_block(key1, 0, salt_value, 20)
|
||||
|
||||
# convert next 8 bytes of secret string into integer (key=0 if secret < 8 chars)
|
||||
key2 = _crypt_secret_to_key(secret[8:16])
|
||||
|
||||
# run data through des using input of 0
|
||||
result2 = des_encrypt_int_block(key2, 0, salt_value, 5)
|
||||
|
||||
# done
|
||||
chk = h64big.encode_int64(result1) + h64big.encode_int64(result2)
|
||||
return chk.decode("ascii")
|
||||
|
||||
#===================================================================
|
||||
# eoc
|
||||
#===================================================================
|
||||
|
||||
#=============================================================================
|
||||
# eof
|
||||
#=============================================================================
|
Reference in New Issue
Block a user