aboutsummaryrefslogtreecommitdiffstats
path: root/docs/fernet.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/fernet.rst')
-rw-r--r--docs/fernet.rst44
1 files changed, 43 insertions, 1 deletions
diff --git a/docs/fernet.rst b/docs/fernet.rst
index eacbc2ae..a2bab32a 100644
--- a/docs/fernet.rst
+++ b/docs/fernet.rst
@@ -3,7 +3,7 @@ Fernet (symmetric encryption)
.. currentmodule:: cryptography.fernet
-Fernet provides guarantees that a message encrypted using it cannot be
+Fernet guarantees that a message encrypted using it cannot be
manipulated or read without the key. `Fernet`_ is an implementation of
symmetric (also known as "secret key") authenticated cryptography. Fernet also
has support for implementing key rotation via :class:`MultiFernet`.
@@ -106,6 +106,47 @@ has support for implementing key rotation via :class:`MultiFernet`.
See :meth:`Fernet.decrypt` for more information.
+
+Using passwords with Fernet
+---------------------------
+
+It is possible to use passwords with Fernet. To do this, you need to run the
+password through a key derivation function such as
+:class:`~cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC`, bcrypt or
+scrypt.
+
+.. doctest::
+
+ >>> import base64
+ >>> import os
+ >>> from cryptography.fernet import Fernet
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
+ >>> password = b"password"
+ >>> salt = os.urandom(16)
+ >>> kdf = PBKDF2HMAC(
+ ... algorithm=hashes.SHA256(),
+ ... length=32,
+ ... salt=salt,
+ ... iterations=100000,
+ ... backend=default_backend()
+ ... )
+ >>> key = base64.urlsafe_b64encode(kdf.derive(password))
+ >>> f = Fernet(key)
+ >>> token = f.encrypt(b"Secret message!")
+ >>> token
+ '...'
+ >>> f.decrypt(token)
+ 'Secret message!'
+
+In this scheme, the salt has to be stored in a retrievable location in order
+to derive the same key from the password in the future.
+
+The iteration count used should be adjusted to be as high as your server can
+tolerate. A good default is at least 100,000 iterations which is what Django
+`recommends`_ in 2014.
+
Implementation
--------------
@@ -125,3 +166,4 @@ For complete details consult the `specification`_.
.. _`Fernet`: https://github.com/fernet/spec/
.. _`specification`: https://github.com/fernet/spec/blob/master/Spec.md
+.. _`recommends`: https://github.com/django/django/blob/master/django/utils/crypto.py#L148