=============================================================
:class:`passlib.hash.grub_pbkdf2_sha512` - Grub's PBKDF2 Hash
=============================================================

.. index:: pbkdf2 hash; grub

.. currentmodule:: passlib.hash

This class provides an implementation of Grub's PBKDF2-HMAC-SHA512
password hash [#grub]_, as generated by the :command:`grub-mkpasswd-pbkdf2` command,
and may be found in Grub2 configuration files.
PBKDF2 is a key derivation function [#pbkdf2]_
that is ideally suited as the basis for a password hash, as it provides
variable length salts, variable number of rounds.

.. seealso::

    * :ref:`password hash usage <password-hash-examples>` --
      for examples of how to use this class via the common hash interface.

    * :doc:`passlib.hash.pbkdf2_{digest} <passlib.hash.pbkdf2_digest>` --
      for some other PBKDF2-based hashes.

Interface
=========
.. autoclass:: grub_pbkdf2_sha512()

Format & Algorithm
==================

A example hash (of ``password``) is ::

    grub.pbkdf2.sha512.10000.4483972AD2C52E1F590B3E2260795FDA9CA0B07B
    96FF492814CA9775F08C4B59CD1707F10B269E09B61B1E2D11729BCA8D62B7827
    B25B093EC58C4C1EAC23137.DF4FCB5DD91340D6D31E33423E4210AD47C7A4DF9
    FA16F401663BF288C20BF973530866178FE6D134256E4DBEFBD984B652332EED3
    ACAED834FEA7B73CAE851D

All of this scheme's hashes have the format :samp:`grub.pbkdf2.sha512.{rounds}.{salt}.{checksum}`,
where :samp:`{rounds}` is the number of iteration stored in decimal,
:samp:`{salt}` is the salt string encoded using upper-case hexadecimal,
and :samp:`{checksum}` is the resulting 64-byte derived key, also
encoded in upper-case hexadecimal. It can be identified by the prefix ``grub.pdkdf2.sha512.``.

The algorithm used is the same as :class:`pbkdf2_sha1`: the password is encoded into UTF-8 if not already encoded,
and passed through :func:`~passlib.crypto.digest.pbkdf1`
along with the decoded salt, and the number of rounds.
The result is then encoded into hexadecimal.

..
    Hash Translation
    ----------------
    Note that despite encoding and format differences,
    :class:`pbkdf2_sha512` and :class:`!grub_pbkdf2_sha512` share an identical algorithm,
    and one can be converted to the other using the following code::

        >>> from passlib.hash import pbkdf2_sha512, grub_pbkdf2_sha512

        >>> # given a pbkdf2_sha512 hash...
        >>> h = pbkdf2_sha512.hash("password")
        >>> h
        '$pbkdf2-sha512$6400$y6vYff3SihJiqumIrNXwGw$NobVwyUlVI52/Cvrguwli5fX6XgKHNUf7fWWS2VgoWEevaTCiZx4OCYhwGFwzUAuz/g1zQVSIf.9JEb0BEVEEA'

        >>> # it can be parsed into options
        >>> hobj = pbkdf2_sha512.from_string(h)
        >>> rounds, salt, chk = hobj.rounds, hobj.salt, hobj.checksum

        >>> # and a new grub hash can be created
        >>> gobj = grub_pbkdf2_sha512(rounds=rounds, salt=salt, checksum=chk)
        >>> g = gobj.to_string()
        >>> g

        >>> grub_pbkdf2_sha512.verify("password", g)
        True

.. rubric:: Footnotes

.. [#grub] Information about Grub's password hashes - `<http://grub.enbug.org/Authentication>`_.

.. [#pbkdf2] The specification for the PBKDF2 algorithm - `<http://tools.ietf.org/html/rfc2898#section-5.2>`_.
