passlib.hash.bsdi_crypt
- BSDi Crypt¶
Danger
This algorithm is not considered secure by modern standards. It should only be used when verifying existing hashes, or when interacting with applications that require this format. For new code, see the list of recommended hashes.
This algorithm was developed by BSDi for their BSD/OS distribution.
It’s based on des_crypt
, and contains a larger
salt and a variable number of rounds. This algorithm is also
known as “Extended DES Crypt”.
It class can be used directly as follows:
>>> from passlib.hash import bsdi_crypt
>>> # generate new salt, hash password
>>> hash = bsdi_crypt.hash("password")
>>> hash
'_7C/.Bf/4gZk10RYRs4Y'
>>> # same, but with explict number of rounds
>>> bsdi_crypt.using(rounds=10001).hash("password")
'_FQ0.amG/zwCMip7DnBk'
>>> # verify password
>>> bsdi_crypt.verify("password", hash)
True
>>> bsdi_crypt.verify("secret", hash)
False
See also
the generic PasswordHash usage examples
Interface¶
-
class
passlib.hash.
bsdi_crypt
¶ This class implements the BSDi-Crypt password hash, and follows the PasswordHash API.
It supports a fixed-length salt, and a variable number of rounds.
The
using()
method accepts the following optional keywords:Parameters: - salt (str) – 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]
. - rounds (int) – Optional number of rounds to use. Defaults to 5001, must be between 1 and 16777215, inclusive.
- relaxed (bool) –
By default, providing an invalid value for one of the other keywords will result in a
ValueError
. Ifrelaxed=True
, and the error can be corrected, aPasslibHashWarning
will be issued instead. Correctable errors includerounds
that are too small or too large, andsalt
strings that are too long.New in version 1.6.
Changed in version 1.6:
hash()
will now issue a warning if an even number of rounds is used (see Security Issues regarding weak DES keys).- salt (str) – 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
Note
This class will use the first available of two possible backends:
- stdlib
crypt()
, if the host OS supports BSDi-Crypt (primarily BSD-derived systems). - a pure Python implementation of BSDi-Crypt built into Passlib.
You can see which backend is in use by calling the get_backend()
method.
Format¶
An example hash (of the string password
) is _EQ0.jzhSVeUyoSqLupI
.
A bsdi_crypt hash string consists of a 20 character string of the form _roundssaltchecksum
.
All characters except the underscore prefix are drawn from [./0-9A-Za-z]
.
_
- the underscore is used to distinguish this scheme from others, such as des-crypt.rounds
is the number of rounds, stored as a 4 characterhash64
-encoded 24-bit integer (EQ0.
in the example).salt
is the salt, stored as as a 4 character hash64-encoded 24-bit integer (jzhS
in the example).checksum
is the checksum, stored as an 11 character hash64-encoded 64-bit integer (VeUyoSqLupI
in the example).
A bsdi_crypt configuration string is also accepted by this module; and has the same format as the hash string, but with the checksum portion omitted.
Algorithm¶
Security Issues¶
BSDi Crypt should not be considered sufficiently secure, for a number of reasons:
- Its use of the DES stream cipher, which is vulnerable to practical pre-image attacks, and considered broken, as well as having too-small key and block sizes.
- The 24-bit salt is too small to defeat rainbow-table attacks (most modern algorithms provide at least a 48-bit salt).
- The fact that it only uses the lower 7 bits of each byte of the password restricts the keyspace which needs to be searched.
- Additionally, even rounds values are slightly weaker still, as they may reveal the hash used one of the weak DES keys [3]. This information could theoretically allow an attacker to perform a brute-force attack on a reduced keyspace and against only 1-2 rounds of DES. (This issue is mitigated by the fact that few passwords are both valid and result in a weak key).
This algorithm is none-the-less stronger than des_crypt
itself,
since it supports variable rounds, a larger salt size,
and uses all the bytes of the password.
Deviations¶
This implementation of bsdi-crypt differs from others in one way:
Unicode Policy:
The original bsdi-crypt 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 bsdi-crypt. If a different encoding is desired by an application, the password should be encoded before handing it to Passlib.
Footnotes
[1] | Primary source used for description of bsdi-crypt format & algorithm - http://fuse4bsd.creo.hu/localcgi/man-cgi.cgi?crypt+3 |
[2] | Another source describing algorithm - http://ftp.lava.net/cgi-bin/bsdi-man?proto=1.1&query=crypt&msection=3&apropos=0 |
[3] | DES weak keys - https://en.wikipedia.org/wiki/Weak_key#Weak_keys_in_DES |