1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
==================================================================
:class:`passlib.hash.mssql2000` - MS SQL 2000 password hash
==================================================================
.. currentmodule:: passlib.hash
This class implements the hash algorithm used by Microsoft SQL Server 2000
to store it's user account passwords, until it was replaced
by a slightly more secure variant (:class:`~passlib.hash.mssql2005`)
in MSSQL 2005.
.. warning::
This hash is not very secure, and should not be used for any purposes
besides manipulating existing MSSQL 2000 password hashes.
.. seealso::
:class:`~passlib.hash.mssql2005`
Usage
=====
This class can be used directly as follows (note that this class requires
a username for all encrypt/verify operations)::
>>> from passlib.hash import mssql2000 as m20
>>> #encrypt password using specified username
>>> h = m20.encrypt("password")
>>> h
'0x0100200420C4988140FD3920894C3EDC188E94F428D57DAD5905F6CC1CBAF950CAD4C63F272B2C91E4DEEB5E6444'
>>> m20.identify(h) #check if hash is recognized
True
>>> m20.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if some other hash is recognized
False
>>> m20.verify("password", h) #verify correct password
True
>>> m20.verify("letmein", h) #verify incorrect password
False
Interface
=========
.. autoclass:: mssql2000()
.. rst-class:: html-toggle
Format & Algorithm
==================
MSSQL 2000 hashes are usually presented as a series of 92 upper-case
hexidecimal characters, prefixed by ``0x``. An example MSSQL 2000 hash
(of ``"password"``)::
0x0100200420C4988140FD3920894C3EDC188E94F428D57DAD5905F6CC1CBAF950CAD4C63F272B2C91E4DEEB5E6444
This encodes 46 bytes of raw data, consisting of:
* a 2-byte constant ``0100``
* 4 byte of salt (``200420C4`` in the example)
* the first 20 byte digest (``988140FD3920894C3EDC188E94F428D57DAD5905``
in the example).
* a second 20 byte digest (``F6CC1CBAF950CAD4C63F272B2C91E4DEEB5E6444``
in the example).
The first digest is generated by encoding the unicode password using
``UTF-16-LE``, and calculating ``SHA1(encoded_secret + salt)``.
The second digest is generated the same as the first,
except that the password is converted to upper-case first.
Only the second digest is used when verifying passwords (and hence the hash
is case-insensitive). The first digest is presumably for forward-compatibility:
MSSQL 2005 removed the second digest, and thus became case sensitive.
.. note::
MSSQL 2000 hashes do not actually have a native textual format, as they
are stored as raw bytes in an SQL table. However, when external programs
deal with them, MSSQL generally encodes raw bytes as upper-case hexidecimal,
prefixed with ``0x``. This is the representation Passlib uses.
Security Issues
===============
This algorithm is reasonably weak, and shouldn't be used for any
purpose besides manipulating existing MSSQL 2000 hashes, due to the
following flaws:
* The fact that it is case insensitive greatly reduces the keyspace that
must be searched by brute-force or pre-computed attacks.
* It's simplicity, and years of research on high-speed SHA1
implementations, makes efficient brute force attacks much more feasible.
.. rubric:: Footnotes
.. [#] Overview hash algorithms used by MSSQL -
`<https://blogs.msdn.com/b/lcris/archive/2007/04/30/sql-server-2005-about-login-password-hashes.aspx?Redirected=true>`_.
.. [#] Description of MSSQL 2000 algorithm -
`<http://www.theregister.co.uk/2002/07/08/cracking_ms_sql_server_passwords/>`_.
|