diff options
Diffstat (limited to 'docs/hazmat/primitives/key-derivation-functions.rst')
| -rw-r--r-- | docs/hazmat/primitives/key-derivation-functions.rst | 497 |
1 files changed, 438 insertions, 59 deletions
diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst index 35e2dd87..4b474124 100644 --- a/docs/hazmat/primitives/key-derivation-functions.rst +++ b/docs/hazmat/primitives/key-derivation-functions.rst @@ -34,7 +34,8 @@ Different KDFs are suitable for different tasks such as: `PBKDF2`_ (Password Based Key Derivation Function 2) is typically used for deriving a cryptographic key from a password. It may also be used for - key storage, but an alternate key storage KDF such as `scrypt`_ is generally + key storage, but an alternate key storage KDF such as + :class:`~cryptography.hazmat.primitives.kdf.scrypt.Scrypt` is generally considered a better solution. This class conforms to the @@ -48,6 +49,7 @@ Different KDFs are suitable for different tasks such as: >>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC >>> from cryptography.hazmat.backends import default_backend >>> backend = default_backend() + >>> # Salts should be randomly generated >>> salt = os.urandom(16) >>> # derive >>> kdf = PBKDF2HMAC( @@ -68,21 +70,19 @@ Different KDFs are suitable for different tasks such as: ... ) >>> kdf.verify(b"my great password", key) - :param algorithm: An instance of a - :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - provider. - :param int length: The desired length of the derived key. Maximum is - (2\ :sup:`32` - 1) * ``algorithm.digest_size``. - :param bytes salt: A salt. `NIST SP 800-132`_ recommends 128-bits or - longer. + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. + :param int length: The desired length of the derived key in bytes. Maximum + is (2\ :sup:`32` - 1) * ``algorithm.digest_size``. + :param bytes salt: A salt. Secure values [#nist]_ are 128-bits (16 bytes) + or longer and randomly generated. :param int iterations: The number of iterations to perform of the hash function. This can be used to control the length of time the operation takes. Higher numbers help mitigate brute force attacks against derived - keys. See OWASP's `Password Storage Cheat Sheet`_ for more - detailed recommendations if you intend to use this for password storage. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend` - provider. + keys. A `more detailed description`_ can be consulted for additional + information. + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.PBKDF2HMACBackend`. :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the provided ``backend`` does not implement @@ -92,8 +92,9 @@ Different KDFs are suitable for different tasks such as: .. method:: derive(key_material) - :param bytes key_material: The input key material. For PBKDF2 this + :param key_material: The input key material. For PBKDF2 this should be a password. + :type key_material: :term:`bytes-like` :return bytes: the derived key. :raises cryptography.exceptions.AlreadyFinalized: This is raised when :meth:`derive` or @@ -168,12 +169,11 @@ Different KDFs are suitable for different tasks such as: ... ) >>> hkdf.verify(b"input key", key) - :param algorithm: An instance of a - :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - provider. + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. - :param int length: The desired length of the derived key. Maximum is - ``255 * (algorithm.digest_size // 8)``. + :param int length: The desired length of the derived key in bytes. Maximum + is ``255 * (algorithm.digest_size // 8)``. :param bytes salt: A salt. Randomizes the KDF's output. Optional, but highly recommended. Ideally as many bits of entropy as the security @@ -181,16 +181,15 @@ Different KDFs are suitable for different tasks such as: long as the hash output. Worse (shorter, less entropy) salt values can still meaningfully contribute to security. May be reused. Does not have to be secret, but may cause stronger security guarantees if secret; see - `RFC 5869`_ and the `HKDF paper`_ for more details. If ``None`` is + :rfc:`5869` and the `HKDF paper`_ for more details. If ``None`` is explicitly passed a default salt of ``algorithm.digest_size // 8`` null bytes will be used. :param bytes info: Application specific context information. If ``None`` is explicitly passed an empty byte string will be used. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` - provider. + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`. :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the provided ``backend`` does not implement @@ -201,10 +200,16 @@ Different KDFs are suitable for different tasks such as: .. method:: derive(key_material) - :param bytes key_material: The input key material. + :param key_material: The input key material. + :type key_material: :term:`bytes-like` :return bytes: The derived key. :raises TypeError: This exception is raised if ``key_material`` is not ``bytes``. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. Derives a new key from the input key material by performing both the extract and expand operations. @@ -269,24 +274,21 @@ Different KDFs are suitable for different tasks such as: ... ) >>> hkdf.verify(key_material, key) - :param algorithm: An instance of a - :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - provider. + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. - :param int length: The desired length of the derived key. Maximum is - ``255 * (algorithm.digest_size // 8)``. + :param int length: The desired length of the derived key in bytes. Maximum + is ``255 * (algorithm.digest_size // 8)``. :param bytes info: Application specific context information. If ``None`` is explicitly passed an empty byte string will be used. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` - provider. + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`. :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the provided ``backend`` does not implement :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` - :raises TypeError: This is raised if the provided ``info`` is a unicode object :raises TypeError: This exception is raised if ``info`` is not ``bytes``. .. method:: derive(key_material) @@ -294,10 +296,13 @@ Different KDFs are suitable for different tasks such as: :param bytes key_material: The input key material. :return bytes: The derived key. - :raises TypeError: This is raised if the provided ``key_material`` is - a unicode object :raises TypeError: This exception is raised if ``key_material`` is not ``bytes``. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. Derives a new key from the input key material by performing both the extract and expand operations. @@ -318,7 +323,7 @@ Different KDFs are suitable for different tasks such as: called more than once. :raises TypeError: This is raised if the provided ``key_material`` is - a unicode object + a ``unicode`` object This checks whether deriving a new key from the supplied ``key_material`` generates the same key as the ``expected_key``, and @@ -348,22 +353,21 @@ Different KDFs are suitable for different tasks such as: >>> otherinfo = b"concatkdf-example" >>> ckdf = ConcatKDFHash( ... algorithm=hashes.SHA256(), - ... length=256, + ... length=32, ... otherinfo=otherinfo, ... backend=backend ... ) >>> key = ckdf.derive(b"input key") >>> ckdf = ConcatKDFHash( ... algorithm=hashes.SHA256(), - ... length=256, + ... length=32, ... otherinfo=otherinfo, ... backend=backend ... ) >>> ckdf.verify(b"input key", key) - :param algorithm: An instance of a - :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - provider + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. :param int length: The desired length of the derived key in bytes. Maximum is ``hashlen * (2^32 -1)``. @@ -371,9 +375,8 @@ Different KDFs are suitable for different tasks such as: :param bytes otherinfo: Application specific context information. If ``None`` is explicitly passed an empty byte string will be used. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.HashBackend` - provider. + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.HashBackend`. :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the provided ``backend`` does not implement @@ -384,10 +387,16 @@ Different KDFs are suitable for different tasks such as: .. method:: derive(key_material) - :param bytes key_material: The input key material. + :param key_material: The input key material. + :type key_material: :term:`bytes-like` :return bytes: The derived key. :raises TypeError: This exception is raised if ``key_material`` is not ``bytes``. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. Derives a new key from the input key material. @@ -433,7 +442,7 @@ Different KDFs are suitable for different tasks such as: >>> otherinfo = b"concatkdf-example" >>> ckdf = ConcatKDFHMAC( ... algorithm=hashes.SHA256(), - ... length=256, + ... length=32, ... salt=salt, ... otherinfo=otherinfo, ... backend=backend @@ -441,16 +450,15 @@ Different KDFs are suitable for different tasks such as: >>> key = ckdf.derive(b"input key") >>> ckdf = ConcatKDFHMAC( ... algorithm=hashes.SHA256(), - ... length=256, + ... length=32, ... salt=salt, ... otherinfo=otherinfo, ... backend=backend ... ) >>> ckdf.verify(b"input key", key) - :param algorithm: An instance of a - :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` - provider + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. :param int length: The desired length of the derived key in bytes. Maximum is ``hashlen * (2^32 -1)``. @@ -466,9 +474,8 @@ Different KDFs are suitable for different tasks such as: :param bytes otherinfo: Application specific context information. If ``None`` is explicitly passed an empty byte string will be used. - :param backend: A - :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` - provider. + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend`. :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the provided ``backend`` does not implement @@ -483,6 +490,241 @@ Different KDFs are suitable for different tasks such as: :return bytes: The derived key. :raises TypeError: This exception is raised if ``key_material`` is not ``bytes``. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. + + Derives a new key from the input key material. + + .. method:: verify(key_material, expected_key) + + :param bytes key_material: The input key material. This is the same as + ``key_material`` in :meth:`derive`. + :param bytes expected_key: The expected result of deriving a new key, + this is the same as the return value of + :meth:`derive`. + :raises cryptography.exceptions.InvalidKey: This is raised when the + derived key does not match + the expected key. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. + + This checks whether deriving a new key from the supplied + ``key_material`` generates the same key as the ``expected_key``, and + raises an exception if they do not match. + +.. currentmodule:: cryptography.hazmat.primitives.kdf.x963kdf + +.. class:: X963KDF(algorithm, length, otherinfo, backend) + + .. versionadded:: 1.1 + + X963KDF (ANSI X9.63 Key Derivation Function) is defined by ANSI + in the `ANSI X9.63:2001`_ document, to be used to derive keys for use + after a Key Exchange negotiation operation. + + SECG in `SEC 1 v2.0`_ recommends that + :class:`~cryptography.hazmat.primitives.kdf.concatkdf.ConcatKDFHash` be + used for new projects. This KDF should only be used for backwards + compatibility with pre-existing protocols. + + + .. warning:: + + X963KDF should not be used for password storage. + + .. doctest:: + + >>> import os + >>> from cryptography.hazmat.primitives import hashes + >>> from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF + >>> from cryptography.hazmat.backends import default_backend + >>> backend = default_backend() + >>> sharedinfo = b"ANSI X9.63 Example" + >>> xkdf = X963KDF( + ... algorithm=hashes.SHA256(), + ... length=32, + ... sharedinfo=sharedinfo, + ... backend=backend + ... ) + >>> key = xkdf.derive(b"input key") + >>> xkdf = X963KDF( + ... algorithm=hashes.SHA256(), + ... length=32, + ... sharedinfo=sharedinfo, + ... backend=backend + ... ) + >>> xkdf.verify(b"input key", key) + + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. + + :param int length: The desired length of the derived key in bytes. + Maximum is ``hashlen * (2^32 -1)``. + + :param bytes sharedinfo: Application specific context information. + If ``None`` is explicitly passed an empty byte string will be used. + + :param backend: A cryptography backend + :class:`~cryptography.hazmat.backends.interfaces.HashBackend` + instance. + + :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised + if the provided ``backend`` does not implement + :class:`~cryptography.hazmat.backends.interfaces.HashBackend` + + :raises TypeError: This exception is raised if ``sharedinfo`` is not + ``bytes``. + + .. method:: derive(key_material) + + :param key_material: The input key material. + :type key_material: :term:`bytes-like` + :return bytes: The derived key. + :raises TypeError: This exception is raised if ``key_material`` is + not ``bytes``. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. + + Derives a new key from the input key material. + + .. method:: verify(key_material, expected_key) + + :param bytes key_material: The input key material. This is the same as + ``key_material`` in :meth:`derive`. + :param bytes expected_key: The expected result of deriving a new key, + this is the same as the return value of + :meth:`derive`. + :raises cryptography.exceptions.InvalidKey: This is raised when the + derived key does not match + the expected key. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. + + This checks whether deriving a new key from the supplied + ``key_material`` generates the same key as the ``expected_key``, and + raises an exception if they do not match. + + +.. currentmodule:: cryptography.hazmat.primitives.kdf.kbkdf + +.. class:: KBKDFHMAC(algorithm, mode, length, rlen, llen, location,\ + label, context, fixed, backend) + + .. versionadded:: 1.4 + + KBKDF (Key Based Key Derivation Function) is defined by the + `NIST SP 800-108`_ document, to be used to derive additional + keys from a key that has been established through an automated + key-establishment scheme. + + .. warning:: + + KBKDFHMAC should not be used for password storage. + + .. doctest:: + + >>> import os + >>> from cryptography.hazmat.primitives import hashes + >>> from cryptography.hazmat.primitives.kdf.kbkdf import ( + ... CounterLocation, KBKDFHMAC, Mode + ... ) + >>> from cryptography.hazmat.backends import default_backend + >>> backend = default_backend() + >>> label = b"KBKDF HMAC Label" + >>> context = b"KBKDF HMAC Context" + >>> kdf = KBKDFHMAC( + ... algorithm=hashes.SHA256(), + ... mode=Mode.CounterMode, + ... length=32, + ... rlen=4, + ... llen=4, + ... location=CounterLocation.BeforeFixed, + ... label=label, + ... context=context, + ... fixed=None, + ... backend=backend + ... ) + >>> key = kdf.derive(b"input key") + >>> kdf = KBKDFHMAC( + ... algorithm=hashes.SHA256(), + ... mode=Mode.CounterMode, + ... length=32, + ... rlen=4, + ... llen=4, + ... location=CounterLocation.BeforeFixed, + ... label=label, + ... context=context, + ... fixed=None, + ... backend=backend + ... ) + >>> kdf.verify(b"input key", key) + + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. + + :param mode: The desired mode of the PRF. A value from the + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.Mode` enum. + + :param int length: The desired length of the derived key in bytes. + + :param int rlen: An integer that indicates the length of the binary + representation of the counter in bytes. + + :param int llen: An integer that indicates the binary + representation of the ``length`` in bytes. + + :param location: The desired location of the counter. A value from the + :class:`~cryptography.hazmat.primitives.kdf.kbkdf.CounterLocation` enum. + + :param bytes label: Application specific label information. If ``None`` + is explicitly passed an empty byte string will be used. + + :param bytes context: Application specific context information. If ``None`` + is explicitly passed an empty byte string will be used. + + :param bytes fixed: Instead of specifying ``label`` and ``context`` you + may supply your own fixed data. If ``fixed`` is specified, ``label`` + and ``context`` is ignored. + + :param backend: A cryptography backend + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + instance. + + :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised + if the provided ``backend`` does not implement + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` + + :raises TypeError: This exception is raised if ``label`` or ``context`` + is not ``bytes``. Also raised if ``rlen`` or ``llen`` is not ``int``. + + :raises ValueError: This exception is raised if ``rlen`` or ``llen`` + is greater than 4 or less than 1. This exception is also raised if + you specify a ``label`` or ``context`` and ``fixed``. + + .. method:: derive(key_material) + + :param key_material: The input key material. + :type key_material: :term:`bytes-like` + :return bytes: The derived key. + :raises TypeError: This exception is raised if ``key_material`` is + not ``bytes``. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. Derives a new key from the input key material. @@ -506,6 +748,137 @@ Different KDFs are suitable for different tasks such as: ``key_material`` generates the same key as the ``expected_key``, and raises an exception if they do not match. +.. class:: Mode + + An enumeration for the key based key derivative modes. + + .. attribute:: CounterMode + + The output of the PRF is computed with a counter + as the iteration variable. + +.. class:: CounterLocation + + An enumeration for the key based key derivative counter location. + + .. attribute:: BeforeFixed + + The counter iteration variable will be concatenated before + the fixed input data. + + .. attribute:: AfterFixed + + The counter iteration variable will be concatenated after + the fixed input data. + +.. currentmodule:: cryptography.hazmat.primitives.kdf.scrypt + +.. class:: Scrypt(salt, length, n, r, p, backend) + + .. versionadded:: 1.6 + + Scrypt is a KDF designed for password storage by Colin Percival to be + resistant against hardware-assisted attackers by having a tunable memory + cost. It is described in :rfc:`7914`. + + This class conforms to the + :class:`~cryptography.hazmat.primitives.kdf.KeyDerivationFunction` + interface. + + .. doctest:: + + >>> import os + >>> from cryptography.hazmat.primitives.kdf.scrypt import Scrypt + >>> from cryptography.hazmat.backends import default_backend + >>> backend = default_backend() + >>> salt = os.urandom(16) + >>> # derive + >>> kdf = Scrypt( + ... salt=salt, + ... length=32, + ... n=2**14, + ... r=8, + ... p=1, + ... backend=backend + ... ) + >>> key = kdf.derive(b"my great password") + >>> # verify + >>> kdf = Scrypt( + ... salt=salt, + ... length=32, + ... n=2**14, + ... r=8, + ... p=1, + ... backend=backend + ... ) + >>> kdf.verify(b"my great password", key) + + :param bytes salt: A salt. + :param int length: The desired length of the derived key in bytes. + :param int n: CPU/Memory cost parameter. It must be larger than 1 and be a + power of 2. + :param int r: Block size parameter. + :param int p: Parallelization parameter. + :param backend: An instance of + :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend`. + + The computational and memory cost of Scrypt can be adjusted by manipulating + the 3 parameters: ``n``, ``r``, and ``p``. In general, the memory cost of + Scrypt is affected by the values of both ``n`` and ``r``, while ``n`` also + determines the number of iterations performed. ``p`` increases the + computational cost without affecting memory usage. A more in-depth + explanation of the 3 parameters can be found `here`_. + + :rfc:`7914` `recommends`_ values of ``r=8`` and ``p=1`` while scaling ``n`` + to a number appropriate for your system. `The scrypt paper`_ suggests a + minimum value of ``n=2**14`` for interactive logins (t < 100ms), or + ``n=2**20`` for more sensitive files (t < 5s). + + :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the + provided ``backend`` does not implement + :class:`~cryptography.hazmat.backends.interfaces.ScryptBackend` + + :raises TypeError: This exception is raised if ``salt`` is not ``bytes``. + :raises ValueError: This exception is raised if ``n`` is less than 2, if + ``n`` is not a power of 2, if ``r`` is less than 1 or if ``p`` is less + than 1. + + .. method:: derive(key_material) + + :param key_material: The input key material. + :type key_material: :term:`bytes-like` + :return bytes: the derived key. + :raises TypeError: This exception is raised if ``key_material`` is not + ``bytes``. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. + + This generates and returns a new key from the supplied password. + + .. method:: verify(key_material, expected_key) + + :param bytes key_material: The input key material. This is the same as + ``key_material`` in :meth:`derive`. + :param bytes expected_key: The expected result of deriving a new key, + this is the same as the return value of + :meth:`derive`. + :raises cryptography.exceptions.InvalidKey: This is raised when the + derived key does not match + the expected key. + :raises cryptography.exceptions.AlreadyFinalized: This is raised when + :meth:`derive` or + :meth:`verify` is + called more than + once. + + This checks whether deriving a new key from the supplied + ``key_material`` generates the same key as the ``expected_key``, and + raises an exception if they do not match. This can be used for + checking whether the password a user provides matches the stored derived + key. Interface ~~~~~~~~~ @@ -554,12 +927,18 @@ Interface stored derived key. -.. _`NIST SP 800-132`: http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf -.. _`NIST SP 800-56Ar2`: http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf -.. _`Password Storage Cheat Sheet`: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet +.. [#nist] See `NIST SP 800-132`_. + +.. _`NIST SP 800-132`: https://csrc.nist.gov/publications/detail/sp/800-132/final +.. _`NIST SP 800-108`: https://csrc.nist.gov/publications/detail/sp/800-108/final +.. _`NIST SP 800-56Ar2`: https://csrc.nist.gov/publications/detail/sp/800-56a/rev-2/final +.. _`ANSI X9.63:2001`: https://webstore.ansi.org +.. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf +.. _`more detailed description`: https://security.stackexchange.com/a/3993/43116 .. _`PBKDF2`: https://en.wikipedia.org/wiki/PBKDF2 -.. _`scrypt`: https://en.wikipedia.org/wiki/Scrypt .. _`key stretching`: https://en.wikipedia.org/wiki/Key_stretching -.. _`HKDF`: -.. _`RFC 5869`: https://tools.ietf.org/html/rfc5869 +.. _`HKDF`: https://en.wikipedia.org/wiki/HKDF .. _`HKDF paper`: https://eprint.iacr.org/2010/264 +.. _`here`: https://stackoverflow.com/a/30308723/1170681 +.. _`recommends`: https://tools.ietf.org/html/rfc7914#section-2 +.. _`The scrypt paper`: https://www.tarsnap.com/scrypt/scrypt.pdf |
