You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							129 lines
						
					
					
						
							4.7 KiB
						
					
					
				
			
		
		
	
	
							129 lines
						
					
					
						
							4.7 KiB
						
					
					
				"""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
 | 
						|
#=============================================================================
 |