blob: 82d94fafb6c66fdf1444fcc5d32a7b6955ffe29d [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
Paul Kehrer765a3e42017-07-05 23:00:41 -050040 Encrypts data passed. The result of this encryption is known as a
41 "Fernet token" and has strong privacy and authenticity guarantees.
42
Ayrx6d69eab2014-05-17 16:59:31 +080043 :param bytes data: The message you would like to encrypt.
Alex Stapleton63b3de22014-02-08 09:43:16 +000044 :returns bytes: A secure message that cannot be read or altered
Alex Gaynor0d089632013-12-17 20:23:43 -080045 without the key. It is URL-safe base64-encoded. This is
Alex Gaynor3aa243c2014-01-06 13:13:18 -080046 referred to as a "Fernet token".
Alex Gaynore148d012014-10-19 19:18:59 -070047 :raises TypeError: This exception is raised if ``data`` is not
48 ``bytes``.
Alex Gaynor32dc4e42013-12-20 13:26:12 -080049
Alex Gaynor719eb6a2013-12-20 13:35:57 -080050 .. note::
Alex Gaynor32dc4e42013-12-20 13:26:12 -080051
52 The encrypted message contains the current time when it was
53 generated in *plaintext*, the time a message was created will
54 therefore be visible to a possible attacker.
Alex Gaynor333fb102013-10-31 10:27:35 -070055
Alex Gaynor0d089632013-12-17 20:23:43 -080056 .. method:: decrypt(token, ttl=None)
Alex Gaynor333fb102013-10-31 10:27:35 -070057
Paul Kehrer765a3e42017-07-05 23:00:41 -050058 Decrypts a Fernet token. If successfully decrypted you will receive the
59 original plaintext as the result, otherwise an exception will be
60 raised. It is safe to use this data immediately as Fernet verifies
61 that the data has not been tampered with prior to returning it.
62
Alex Gaynor0d089632013-12-17 20:23:43 -080063 :param bytes token: The Fernet token. This is the result of calling
64 :meth:`encrypt`.
Alex Gaynor333fb102013-10-31 10:27:35 -070065 :param int ttl: Optionally, the number of seconds old a message may be
66 for it to be valid. If the message is older than
67 ``ttl`` seconds (from the time it was originally
Alex Gaynor13e0d542013-10-31 10:38:04 -070068 created) an exception will be raised. If ``ttl`` is not
69 provided (or is ``None``), the age of the message is
70 not considered.
Alex Gaynor333fb102013-10-31 10:27:35 -070071 :returns bytes: The original plaintext.
Alex Gaynor719eb6a2013-12-20 13:35:57 -080072 :raises cryptography.fernet.InvalidToken: If the ``token`` is in any
73 way invalid, this exception
74 is raised. A token may be
75 invalid for a number of
76 reasons: it is older than the
77 ``ttl``, it is malformed, or
78 it does not have a valid
79 signature.
Alex Gaynore148d012014-10-19 19:18:59 -070080 :raises TypeError: This exception is raised if ``token`` is not
81 ``bytes``.
82
83
84.. class:: MultiFernet(fernets)
85
Alex Gaynor4c825132014-10-20 21:27:08 -070086 .. versionadded:: 0.7
87
Alex Gaynore148d012014-10-19 19:18:59 -070088 This class implements key rotation for Fernet. It takes a ``list`` of
89 :class:`Fernet` instances, and implements the same API:
90
91 .. doctest::
92
93 >>> from cryptography.fernet import Fernet, MultiFernet
94 >>> key1 = Fernet(Fernet.generate_key())
95 >>> key2 = Fernet(Fernet.generate_key())
96 >>> f = MultiFernet([key1, key2])
97 >>> token = f.encrypt(b"Secret message!")
98 >>> token
99 '...'
100 >>> f.decrypt(token)
101 'Secret message!'
102
Terry Chiaeab0d192015-03-26 08:56:28 +0800103 MultiFernet performs all encryption options using the *first* key in the
104 ``list`` provided. MultiFernet attempts to decrypt tokens with each key in
Terry Chia7ff93622015-03-28 02:01:34 +0800105 turn. A :class:`cryptography.fernet.InvalidToken` exception is raised if
Terry Chiaeab0d192015-03-26 08:56:28 +0800106 the correct key is not found in the ``list`` provided.
Alex Gaynore148d012014-10-19 19:18:59 -0700107
108 Key rotation makes it easy to replace old keys. You can add your new key at
109 the front of the list to start encrypting new messages, and remove old keys
110 as they are no longer needed.
Alex Gaynor7a121fc2013-11-22 10:18:30 -0800111
112
113.. class:: InvalidToken
114
115 See :meth:`Fernet.decrypt` for more information.
Alex Gaynor333fb102013-10-31 10:27:35 -0700116
Terry Chiab964a5c2015-08-29 18:53:47 +0800117
118Using passwords with Fernet
119---------------------------
120
121It is possible to use passwords with Fernet. To do this, you need to run the
Terry Chia7126e612015-08-29 22:28:51 +0800122password through a key derivation function such as
Terry Chiab1903b02015-08-30 11:09:22 +0800123:class:`~cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC`, bcrypt or
Alex Gaynor4e87cf42017-01-21 08:50:53 -0500124:class:`~cryptography.hazmat.primitives.kdf.scrypt.Scrypt`.
Terry Chiab964a5c2015-08-29 18:53:47 +0800125
Paul Kehrer8d242c72015-09-04 14:08:10 -0500126.. doctest::
Terry Chiab964a5c2015-08-29 18:53:47 +0800127
Paul Kehrer8d242c72015-09-04 14:08:10 -0500128 >>> import base64
129 >>> import os
130 >>> from cryptography.fernet import Fernet
131 >>> from cryptography.hazmat.backends import default_backend
132 >>> from cryptography.hazmat.primitives import hashes
133 >>> from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
134 >>> password = b"password"
135 >>> salt = os.urandom(16)
136 >>> kdf = PBKDF2HMAC(
137 ... algorithm=hashes.SHA256(),
138 ... length=32,
139 ... salt=salt,
140 ... iterations=100000,
141 ... backend=default_backend()
142 ... )
143 >>> key = base64.urlsafe_b64encode(kdf.derive(password))
144 >>> f = Fernet(key)
145 >>> token = f.encrypt(b"Secret message!")
146 >>> token
147 '...'
148 >>> f.decrypt(token)
149 'Secret message!'
Terry Chiab964a5c2015-08-29 18:53:47 +0800150
151In this scheme, the salt has to be stored in a retrievable location in order
152to derive the same key from the password in the future.
153
154The iteration count used should be adjusted to be as high as your server can
Terry Chia7126e612015-08-29 22:28:51 +0800155tolerate. A good default is at least 100,000 iterations which is what Django
Alex Gaynor4e87cf42017-01-21 08:50:53 -0500156recommended in 2014.
Terry Chiab964a5c2015-08-29 18:53:47 +0800157
Alex Gaynorb32b4912014-01-23 16:24:13 -0600158Implementation
159--------------
160
161Fernet is built on top of a number of standard cryptographic primitives.
162Specifically it uses:
163
164* :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` in
165 :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode with a
166 128-bit key for encryption; using
Alex Gaynor8e6b3312014-06-30 11:39:27 -0700167 :class:`~cryptography.hazmat.primitives.padding.PKCS7` padding.
Alex Gaynorb32b4912014-01-23 16:24:13 -0600168* :class:`~cryptography.hazmat.primitives.hmac.HMAC` using
169 :class:`~cryptography.hazmat.primitives.hashes.SHA256` for authentication.
170* Initialization vectors are generated using ``os.urandom()``.
171
172For complete details consult the `specification`_.
173
Paul Kehrerafa84f12017-05-27 15:11:24 -0500174Limitations
175-----------
176
177Fernet is ideal for encrypting data that easily fits in memory. As a design
178feature it does not expose unauthenticated bytes. Unfortunately, this makes it
179generally unsuitable for very large files at this time.
180
Alex Gaynor333fb102013-10-31 10:27:35 -0700181
182.. _`Fernet`: https://github.com/fernet/spec/
Alex Gaynorb32b4912014-01-23 16:24:13 -0600183.. _`specification`: https://github.com/fernet/spec/blob/master/Spec.md