129 lines
4.7 KiB
Python
129 lines
4.7 KiB
Python
"""passlib.handlers.mysql
|
|
|
|
MySQL 3.2.3 / OLD_PASSWORD()
|
|
|
|
This implements Mysql's OLD_PASSWORD algorithm, introduced in version 3.2.3, deprecated in version 4.1.
|
|
|
|
See :mod:`passlib.handlers.mysql_41` for the new algorithm was put in place in version 4.1
|
|
|
|
This algorithm is known to be very insecure, and should only be used to verify existing password hashes.
|
|
|
|
http://djangosnippets.org/snippets/1508/
|
|
|
|
MySQL 4.1.1 / NEW PASSWORD
|
|
This implements Mysql new PASSWORD algorithm, introduced in version 4.1.
|
|
|
|
This function is unsalted, and therefore not very secure against rainbow attacks.
|
|
It should only be used when dealing with mysql passwords,
|
|
for all other purposes, you should use a salted hash function.
|
|
|
|
Description taken from http://dev.mysql.com/doc/refman/6.0/en/password-hashing.html
|
|
"""
|
|
#=============================================================================
|
|
# imports
|
|
#=============================================================================
|
|
# core
|
|
from hashlib import sha1
|
|
import re
|
|
import logging; log = logging.getLogger(__name__)
|
|
from warnings import warn
|
|
# site
|
|
# pkg
|
|
from passlib.utils import to_native_str
|
|
from passlib.utils.compat import bascii_to_str, unicode, u, \
|
|
byte_elem_value, str_to_uascii
|
|
import passlib.utils.handlers as uh
|
|
# local
|
|
__all__ = [
|
|
'mysql323',
|
|
'mysq41',
|
|
]
|
|
|
|
#=============================================================================
|
|
# backend
|
|
#=============================================================================
|
|
class mysql323(uh.StaticHandler):
|
|
"""This class implements the MySQL 3.2.3 password hash, and follows the :ref:`password-hash-api`.
|
|
|
|
It has no salt and a single fixed round.
|
|
|
|
The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.PasswordHash.genconfig` methods accept no optional keywords.
|
|
"""
|
|
#===================================================================
|
|
# class attrs
|
|
#===================================================================
|
|
name = "mysql323"
|
|
checksum_size = 16
|
|
checksum_chars = uh.HEX_CHARS
|
|
|
|
#===================================================================
|
|
# methods
|
|
#===================================================================
|
|
@classmethod
|
|
def _norm_hash(cls, hash):
|
|
return hash.lower()
|
|
|
|
def _calc_checksum(self, secret):
|
|
# FIXME: no idea if mysql has a policy about handling unicode passwords
|
|
if isinstance(secret, unicode):
|
|
secret = secret.encode("utf-8")
|
|
|
|
MASK_32 = 0xffffffff
|
|
MASK_31 = 0x7fffffff
|
|
WHITE = b' \t'
|
|
|
|
nr1 = 0x50305735
|
|
nr2 = 0x12345671
|
|
add = 7
|
|
for c in secret:
|
|
if c in WHITE:
|
|
continue
|
|
tmp = byte_elem_value(c)
|
|
nr1 ^= ((((nr1 & 63)+add)*tmp) + (nr1 << 8)) & MASK_32
|
|
nr2 = (nr2+((nr2 << 8) ^ nr1)) & MASK_32
|
|
add = (add+tmp) & MASK_32
|
|
return u("%08x%08x") % (nr1 & MASK_31, nr2 & MASK_31)
|
|
|
|
#===================================================================
|
|
# eoc
|
|
#===================================================================
|
|
|
|
#=============================================================================
|
|
# handler
|
|
#=============================================================================
|
|
class mysql41(uh.StaticHandler):
|
|
"""This class implements the MySQL 4.1 password hash, and follows the :ref:`password-hash-api`.
|
|
|
|
It has no salt and a single fixed round.
|
|
|
|
The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.PasswordHash.genconfig` methods accept no optional keywords.
|
|
"""
|
|
#===================================================================
|
|
# class attrs
|
|
#===================================================================
|
|
name = "mysql41"
|
|
_hash_prefix = u("*")
|
|
checksum_chars = uh.HEX_CHARS
|
|
checksum_size = 40
|
|
|
|
#===================================================================
|
|
# methods
|
|
#===================================================================
|
|
@classmethod
|
|
def _norm_hash(cls, hash):
|
|
return hash.upper()
|
|
|
|
def _calc_checksum(self, secret):
|
|
# FIXME: no idea if mysql has a policy about handling unicode passwords
|
|
if isinstance(secret, unicode):
|
|
secret = secret.encode("utf-8")
|
|
return str_to_uascii(sha1(sha1(secret).digest()).hexdigest()).upper()
|
|
|
|
#===================================================================
|
|
# eoc
|
|
#===================================================================
|
|
|
|
#=============================================================================
|
|
# eof
|
|
#=============================================================================
|