passlib.hash.crypt16 - Crypt16¶
Danger
This algorithm is dangerously insecure by modern standards. It is trivially broken, and should not be used if at all possible. For new code, see the list of recommended hashes.
This class implements the Crypt16 password hash, commonly
found on Ultrix and Tru64. It's a minor modification of des_crypt,
which allows passwords of up to 16 characters.
Tip
password hash usage -- for examples of how to use this class via the common hash interface.
Interface¶
crypt16
¶
crypt16(salt=None, **kwds)
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:
Parameters:
-
salt(str, default:None) –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]. -
truncate_error(bool) –By default, crypt16 will silently truncate passwords larger than 16 bytes. Setting
truncate_error=Truewill cause :meth:~passlib.ifc.PasswordHash.hashto raise a :exc:~passlib.exc.PasswordTruncateErrorinstead... versionadded:: 1.7
-
relaxed(bool) –By default, providing an invalid value for one of the other keywords will result in a :exc:
ValueError. Ifrelaxed=True, and the error can be corrected, a :exc:~passlib.exc.PasslibHashWarningwill be issued instead. Correctable errors includesaltstrings that are too long... versionadded:: 1.6
encrypt
classmethod
¶
encrypt(*args, **kwds)
Legacy alias for :meth:hash.
.. deprecated:: 1.7
This method was renamed to :meth:!hash in version 1.7.
This alias will be removed in version 2.0, and should only
be used for compatibility with Passlib 1.3 - 1.6.
parsehash
classmethod
¶
parsehash(hash, checksum=True, sanitize=False)
[experimental method] parse hash into dictionary of settings.
this essentially acts as the inverse of :meth:hash: for most
cases, if hash = cls.hash(secret, **opts), then
cls.parsehash(hash) will return a dict matching the original options
(with the extra keyword checksum).
this method may not work correctly for all hashes, and may not be available on some few. its interface may change in future releases, if it's kept around at all.
Parameters:
-
hash–hash to parse
-
checksum–include checksum keyword? (defaults to True)
-
sanitize–mask data for sensitive fields? (defaults to False)
bitsize
classmethod
¶
bitsize(salt_size=None, **kwds)
[experimental method] return info about bitsizes of hash
default_salt_chars
¶
default_salt_chars()
charset used to generate new salt strings (defaults to salt_chars)
Format¶
An example hash (of the string passphrase) is aaX/UmCcBrceQ0kQGGWKTbuE.
A crypt16 hash string has the format {salt}{checksum_1}{checksum_2}, where:
-
{salt}is the salt, stored as a 2 characterhash64 <passlib.utils.binary.h64>-encoded 12-bit integer (aain the example). -
each
{checksum_i}is a separate checksum, stored as an 11 characterhash64-big <passlib.utils.binary.h64big>-encoded 64-bit integer (X/UmCcBrceQand0kQGGWKTbuEin the example).
Note
This hash is frequently confused with the bigcrypt
hash algorithm, as it has the same size and uses the same character
set as a bigcrypt hash of a password with 9 to 16
characters; though the actual algorithms are different.
Algorithm¶
The crypt16 algorithm uses a weakened version of the des-crypt algorithm:
-
Given a password string and a salt string.
-
The 2 character salt string is decoded to a 12-bit integer salt value; The salt string uses little-endian
hash64 <passlib.utils.binary.h64>encoding. -
If the password is larger than 16 bytes, the end is truncated to 16 bytes. If the password is smaller than 16 bytes, the end is NULL padded to 16 bytes.
-
The lower 7 bits of the first 8 characters of the password are used to form a 56-bit integer; with the first character providing the most significant 7 bits, and the 8th character providing the least significant 7 bits.
-
20 repeated rounds of modified DES encryption are performed; starting with a null input block, and using the 56-bit integer from step 4 as the DES key.
The salt value from step 2 is used to to mutate the normal
DES encrypt operation by swapping bits {i} and {i}+24
in the DES E-Box output if and only if bit {i} is set in
the salt value.
-
The 64-bit result of the last round of step 5 is then lsb-padded with 2 zero bits.
-
The resulting 66-bit integer is encoded in big-endian order using the
hash64-big <passlib.utils.binary.h64big>format. This is the first checksum segment. -
The second checksum segment is created by repeating steps 4..7 using the second 8 bytes of the padding password (from step 3). The only difference is that step 5 uses only 5 rounds.
-
The final checksum string is the concatenation of the two checksum segments, in order.
Security Issues¶
Crypt16 is dangerously flawed:
-
It suffers from all the flaws of
des_crypt. -
Compared to des-crypt, its smaller number of rounds makes it even more vulnerable to brute-force attacks.
-
For a given salt, passwords under 9 characters all have the same 2nd checksum. Given the 12-bit salt size, all such 2nd checksums can be easily pre-computed; making an attack easier, and giving away information about password size.
-
Since both checksums use the same salt, they can be attacked at once (by doing 5 rounds, checking the result against checksum 2, doing 15 rounds more, and checking the result against checksum 1).
Deviations¶
This implementation of crypt16 deviates from public documentation of the format in one way:
- Unicode Policy:
The original crypt16 algorithm was designed for 7-bit us-ascii encoding only
(as evidenced by the fact that it discards the 8th bit of all password bytes).
In order to provide support for unicode strings,
Passlib will encode unicode passwords using utf-8
before running them through crypt16. If a different
encoding is desired by an application, the password should be encoded
before handing it to Passlib.
References¶
- One source of information about bigcrypt & crypt16 - http://www.mail-archive.com/exim-dev@exim.org/msg00970.html