==================================================================
:class:`passlib.hash.mssql2000` - MS SQL 2000 password hash
==================================================================

.. include:: ../_fragments/insecure_hash_warning.rst

.. versionadded:: 1.6

.. currentmodule:: passlib.hash

This class implements the hash algorithm used by Microsoft SQL Server 2000
to store its user account passwords, until it was replaced
by a slightly more secure variant (:class:`~passlib.hash.mssql2005`)
in MSSQL 2005.
This class can be used directly as follows::

    >>> from passlib.hash import mssql2000 as m20

    >>> # hash password
    >>> h = m20.hash("password")
    >>> h
    '0x0100200420C4988140FD3920894C3EDC188E94F428D57DAD5905F6CC1CBAF950CAD4C63F272B2C91E4DEEB5E6444'

    >>> # verify correct password
    >>> m20.verify("password", h)
    True
    >>> m20.verify("letmein", h)
    False

.. seealso::

    * :ref:`password hash usage <password-hash-examples>` -- for more usage examples

    * :doc:`mssql2005 <passlib.hash.mssql2005>` -- the successor to this hash.

Interface
=========
.. autoclass:: mssql2000()

.. rst-class:: html-toggle

Format & Algorithm
==================
MSSQL 2000 hashes are usually presented as a series of 92 upper-case
hexadecimal 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 hexadecimal,
    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.

* Its 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/>`_.
