blob: 0c1eb43d42d31cbbee9ae969d788c9519b539d9b [file] [log] [blame]
Alex Stapletonc5fffd32014-03-18 15:29:00 +00001Fernet (symmetric encryption)
Alex Gaynore9083292013-12-17 16:56:29 -08002=============================
Alex Gaynor333fb102013-10-31 10:27:35 -07003
4.. currentmodule:: cryptography.fernet
5
Fran Fitzpatrick238c1912015-08-25 21:22:30 -04006Fernet guarantees that a message encrypted using it cannot be
Alex Gaynor681fca82013-12-31 14:13:39 -08007manipulated or read without the key. `Fernet`_ is an implementation of
Alex Gaynore148d012014-10-19 19:18:59 -07008symmetric (also known as "secret key") authenticated cryptography. Fernet also
9has support for implementing key rotation via :class:`MultiFernet`.
Alex Gaynor333fb102013-10-31 10:27:35 -070010
11.. class:: Fernet(key)
12
13 This class provides both encryption and decryption facilities.
14
15 .. doctest::
16
17 >>> from cryptography.fernet import Fernet
Alex Gaynor36597b42013-11-22 10:25:13 -080018 >>> key = Fernet.generate_key()
Alex Gaynor333fb102013-10-31 10:27:35 -070019 >>> f = Fernet(key)
Alex Gaynor0d089632013-12-17 20:23:43 -080020 >>> token = f.encrypt(b"my deep dark secret")
21 >>> token
Alex Gaynorde475eb2013-10-31 10:35:19 -070022 '...'
Alex Gaynor0d089632013-12-17 20:23:43 -080023 >>> f.decrypt(token)
Alex Gaynor333fb102013-10-31 10:27:35 -070024 'my deep dark secret'
25
Alex Gaynor7a121fc2013-11-22 10:18:30 -080026 :param bytes key: A URL-safe base64-encoded 32-byte key. This **must** be
27 kept secret. Anyone with this key is able to create and
28 read messages.
Alex Gaynor333fb102013-10-31 10:27:35 -070029
Alex Gaynor36597b42013-11-22 10:25:13 -080030 .. classmethod:: generate_key()
31
32 Generates a fresh fernet key. Keep this some place safe! If you lose it
33 you'll no longer be able to decrypt messages; if anyone else gains
Alex Gaynor6cf242b2013-12-16 11:17:07 -080034 access to it, they'll be able to decrypt all of your messages, and
Alex Stapleton63b3de22014-02-08 09:43:16 +000035 they'll also be able forge arbitrary messages that will be
Alex Gaynor6cf242b2013-12-16 11:17:07 -080036 authenticated and decrypted.
Alex Gaynor333fb102013-10-31 10:27:35 -070037
Ayrx6d69eab2014-05-17 16:59:31 +080038 .. method:: encrypt(data)
Alex Gaynor333fb102013-10-31 10:27:35 -070039
Ayrx6d69eab2014-05-17 16:59:31 +080040 :param bytes data: The message you would like to encrypt.
Alex Stapleton63b3de22014-02-08 09:43:16 +000041 :returns bytes: A secure message that cannot be read or altered
Alex Gaynor0d089632013-12-17 20:23:43 -080042 without the key. It is URL-safe base64-encoded. This is
Alex Gaynor3aa243c2014-01-06 13:13:18 -080043 referred to as a "Fernet token".
Alex Gaynore148d012014-10-19 19:18:59 -070044 :raises TypeError: This exception is raised if ``data`` is not
45 ``bytes``.
Alex Gaynor32dc4e42013-12-20 13:26:12 -080046
Alex Gaynor719eb6a2013-12-20 13:35:57 -080047 .. note::
Alex Gaynor32dc4e42013-12-20 13:26:12 -080048
49 The encrypted message contains the current time when it was
50 generated in *plaintext*, the time a message was created will
51 therefore be visible to a possible attacker.
Alex Gaynor333fb102013-10-31 10:27:35 -070052
Alex Gaynor0d089632013-12-17 20:23:43 -080053 .. method:: decrypt(token, ttl=None)
Alex Gaynor333fb102013-10-31 10:27:35 -070054
Alex Gaynor0d089632013-12-17 20:23:43 -080055 :param bytes token: The Fernet token. This is the result of calling
56 :meth:`encrypt`.
Alex Gaynor333fb102013-10-31 10:27:35 -070057 :param int ttl: Optionally, the number of seconds old a message may be
58 for it to be valid. If the message is older than
59 ``ttl`` seconds (from the time it was originally
Alex Gaynor13e0d542013-10-31 10:38:04 -070060 created) an exception will be raised. If ``ttl`` is not
61 provided (or is ``None``), the age of the message is
62 not considered.
Alex Gaynor333fb102013-10-31 10:27:35 -070063 :returns bytes: The original plaintext.
Alex Gaynor719eb6a2013-12-20 13:35:57 -080064 :raises cryptography.fernet.InvalidToken: If the ``token`` is in any
65 way invalid, this exception
66 is raised. A token may be
67 invalid for a number of
68 reasons: it is older than the
69 ``ttl``, it is malformed, or
70 it does not have a valid
71 signature.
Alex Gaynore148d012014-10-19 19:18:59 -070072 :raises TypeError: This exception is raised if ``token`` is not
73 ``bytes``.
74
75
76.. class:: MultiFernet(fernets)
77
Alex Gaynor4c825132014-10-20 21:27:08 -070078 .. versionadded:: 0.7
79
Alex Gaynore148d012014-10-19 19:18:59 -070080 This class implements key rotation for Fernet. It takes a ``list`` of
81 :class:`Fernet` instances, and implements the same API:
82
83 .. doctest::
84
85 >>> from cryptography.fernet import Fernet, MultiFernet
86 >>> key1 = Fernet(Fernet.generate_key())
87 >>> key2 = Fernet(Fernet.generate_key())
88 >>> f = MultiFernet([key1, key2])
89 >>> token = f.encrypt(b"Secret message!")
90 >>> token
91 '...'
92 >>> f.decrypt(token)
93 'Secret message!'
94
Terry Chiaeab0d192015-03-26 08:56:28 +080095 MultiFernet performs all encryption options using the *first* key in the
96 ``list`` provided. MultiFernet attempts to decrypt tokens with each key in
Terry Chia7ff93622015-03-28 02:01:34 +080097 turn. A :class:`cryptography.fernet.InvalidToken` exception is raised if
Terry Chiaeab0d192015-03-26 08:56:28 +080098 the correct key is not found in the ``list`` provided.
Alex Gaynore148d012014-10-19 19:18:59 -070099
100 Key rotation makes it easy to replace old keys. You can add your new key at
101 the front of the list to start encrypting new messages, and remove old keys
102 as they are no longer needed.
Alex Gaynor7a121fc2013-11-22 10:18:30 -0800103
104
105.. class:: InvalidToken
106
107 See :meth:`Fernet.decrypt` for more information.
Alex Gaynor333fb102013-10-31 10:27:35 -0700108
Terry Chiab964a5c2015-08-29 18:53:47 +0800109
110Using passwords with Fernet
111---------------------------
112
113It is possible to use passwords with Fernet. To do this, you need to run the
Terry Chia7126e612015-08-29 22:28:51 +0800114password through a key derivation function such as
Terry Chiab1903b02015-08-30 11:09:22 +0800115:class:`~cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC`, bcrypt or
Alex Gaynor4e87cf42017-01-21 08:50:53 -0500116:class:`~cryptography.hazmat.primitives.kdf.scrypt.Scrypt`.
Terry Chiab964a5c2015-08-29 18:53:47 +0800117
Paul Kehrer8d242c72015-09-04 14:08:10 -0500118.. doctest::
Terry Chiab964a5c2015-08-29 18:53:47 +0800119
Paul Kehrer8d242c72015-09-04 14:08:10 -0500120 >>> import base64
121 >>> import os
122 >>> from cryptography.fernet import Fernet
123 >>> from cryptography.hazmat.backends import default_backend
124 >>> from cryptography.hazmat.primitives import hashes
125 >>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
126 >>> password = b"password"
127 >>> salt = os.urandom(16)
128 >>> kdf = PBKDF2HMAC(
129 ... algorithm=hashes.SHA256(),
130 ... length=32,
131 ... salt=salt,
132 ... iterations=100000,
133 ... backend=default_backend()
134 ... )
135 >>> key = base64.urlsafe_b64encode(kdf.derive(password))
136 >>> f = Fernet(key)
137 >>> token = f.encrypt(b"Secret message!")
138 >>> token
139 '...'
140 >>> f.decrypt(token)
141 'Secret message!'
Terry Chiab964a5c2015-08-29 18:53:47 +0800142
143In this scheme, the salt has to be stored in a retrievable location in order
144to derive the same key from the password in the future.
145
146The iteration count used should be adjusted to be as high as your server can
Terry Chia7126e612015-08-29 22:28:51 +0800147tolerate. A good default is at least 100,000 iterations which is what Django
Alex Gaynor4e87cf42017-01-21 08:50:53 -0500148recommended in 2014.
Terry Chiab964a5c2015-08-29 18:53:47 +0800149
Alex Gaynorb32b4912014-01-23 16:24:13 -0600150Implementation
151--------------
152
153Fernet is built on top of a number of standard cryptographic primitives.
154Specifically it uses:
155
156* :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` in
157 :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode with a
158 128-bit key for encryption; using
Alex Gaynor8e6b3312014-06-30 11:39:27 -0700159 :class:`~cryptography.hazmat.primitives.padding.PKCS7` padding.
Alex Gaynorb32b4912014-01-23 16:24:13 -0600160* :class:`~cryptography.hazmat.primitives.hmac.HMAC` using
161 :class:`~cryptography.hazmat.primitives.hashes.SHA256` for authentication.
162* Initialization vectors are generated using ``os.urandom()``.
163
164For complete details consult the `specification`_.
165
Alex Gaynor333fb102013-10-31 10:27:35 -0700166
167.. _`Fernet`: https://github.com/fernet/spec/
Alex Gaynorb32b4912014-01-23 16:24:13 -0600168.. _`specification`: https://github.com/fernet/spec/blob/master/Spec.md