Alex Stapleton | c5fffd3 | 2014-03-18 15:29:00 +0000 | [diff] [blame] | 1 | Fernet (symmetric encryption) |
Alex Gaynor | e908329 | 2013-12-17 16:56:29 -0800 | [diff] [blame] | 2 | ============================= |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 3 | |
| 4 | .. currentmodule:: cryptography.fernet |
| 5 | |
Alex Gaynor | 681fca8 | 2013-12-31 14:13:39 -0800 | [diff] [blame] | 6 | Fernet provides guarantees that a message encrypted using it cannot be |
| 7 | manipulated or read without the key. `Fernet`_ is an implementation of |
Alex Gaynor | e148d01 | 2014-10-19 19:18:59 -0700 | [diff] [blame] | 8 | symmetric (also known as "secret key") authenticated cryptography. Fernet also |
| 9 | has support for implementing key rotation via :class:`MultiFernet`. |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 10 | |
| 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 Gaynor | 36597b4 | 2013-11-22 10:25:13 -0800 | [diff] [blame] | 18 | >>> key = Fernet.generate_key() |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 19 | >>> f = Fernet(key) |
Alex Gaynor | 0d08963 | 2013-12-17 20:23:43 -0800 | [diff] [blame] | 20 | >>> token = f.encrypt(b"my deep dark secret") |
| 21 | >>> token |
Alex Gaynor | de475eb | 2013-10-31 10:35:19 -0700 | [diff] [blame] | 22 | '...' |
Alex Gaynor | 0d08963 | 2013-12-17 20:23:43 -0800 | [diff] [blame] | 23 | >>> f.decrypt(token) |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 24 | 'my deep dark secret' |
| 25 | |
Alex Gaynor | 7a121fc | 2013-11-22 10:18:30 -0800 | [diff] [blame] | 26 | :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 Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 29 | |
Alex Gaynor | 36597b4 | 2013-11-22 10:25:13 -0800 | [diff] [blame] | 30 | .. 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 Gaynor | 6cf242b | 2013-12-16 11:17:07 -0800 | [diff] [blame] | 34 | access to it, they'll be able to decrypt all of your messages, and |
Alex Stapleton | 63b3de2 | 2014-02-08 09:43:16 +0000 | [diff] [blame] | 35 | they'll also be able forge arbitrary messages that will be |
Alex Gaynor | 6cf242b | 2013-12-16 11:17:07 -0800 | [diff] [blame] | 36 | authenticated and decrypted. |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 37 | |
Ayrx | 6d69eab | 2014-05-17 16:59:31 +0800 | [diff] [blame] | 38 | .. method:: encrypt(data) |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 39 | |
Ayrx | 6d69eab | 2014-05-17 16:59:31 +0800 | [diff] [blame] | 40 | :param bytes data: The message you would like to encrypt. |
Alex Stapleton | 63b3de2 | 2014-02-08 09:43:16 +0000 | [diff] [blame] | 41 | :returns bytes: A secure message that cannot be read or altered |
Alex Gaynor | 0d08963 | 2013-12-17 20:23:43 -0800 | [diff] [blame] | 42 | without the key. It is URL-safe base64-encoded. This is |
Alex Gaynor | 3aa243c | 2014-01-06 13:13:18 -0800 | [diff] [blame] | 43 | referred to as a "Fernet token". |
Alex Gaynor | e148d01 | 2014-10-19 19:18:59 -0700 | [diff] [blame] | 44 | :raises TypeError: This exception is raised if ``data`` is not |
| 45 | ``bytes``. |
Alex Gaynor | 32dc4e4 | 2013-12-20 13:26:12 -0800 | [diff] [blame] | 46 | |
Alex Gaynor | 719eb6a | 2013-12-20 13:35:57 -0800 | [diff] [blame] | 47 | .. note:: |
Alex Gaynor | 32dc4e4 | 2013-12-20 13:26:12 -0800 | [diff] [blame] | 48 | |
| 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 Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 52 | |
Alex Gaynor | 0d08963 | 2013-12-17 20:23:43 -0800 | [diff] [blame] | 53 | .. method:: decrypt(token, ttl=None) |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 54 | |
Alex Gaynor | 0d08963 | 2013-12-17 20:23:43 -0800 | [diff] [blame] | 55 | :param bytes token: The Fernet token. This is the result of calling |
| 56 | :meth:`encrypt`. |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 57 | :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 Gaynor | 13e0d54 | 2013-10-31 10:38:04 -0700 | [diff] [blame] | 60 | 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 Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 63 | :returns bytes: The original plaintext. |
Alex Gaynor | 719eb6a | 2013-12-20 13:35:57 -0800 | [diff] [blame] | 64 | :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 Gaynor | e148d01 | 2014-10-19 19:18:59 -0700 | [diff] [blame] | 72 | :raises TypeError: This exception is raised if ``token`` is not |
| 73 | ``bytes``. |
| 74 | |
| 75 | |
| 76 | .. class:: MultiFernet(fernets) |
| 77 | |
Alex Gaynor | 4c82513 | 2014-10-20 21:27:08 -0700 | [diff] [blame] | 78 | .. versionadded:: 0.7 |
| 79 | |
Alex Gaynor | e148d01 | 2014-10-19 19:18:59 -0700 | [diff] [blame] | 80 | 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 Chia | eab0d19 | 2015-03-26 08:56:28 +0800 | [diff] [blame] | 95 | MultiFernet performs all encryption options using the *first* key in the |
| 96 | ``list`` provided. MultiFernet attempts to decrypt tokens with each key in |
Terry Chia | 7ff9362 | 2015-03-28 02:01:34 +0800 | [diff] [blame] | 97 | turn. A :class:`cryptography.fernet.InvalidToken` exception is raised if |
Terry Chia | eab0d19 | 2015-03-26 08:56:28 +0800 | [diff] [blame] | 98 | the correct key is not found in the ``list`` provided. |
Alex Gaynor | e148d01 | 2014-10-19 19:18:59 -0700 | [diff] [blame] | 99 | |
| 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 Gaynor | 7a121fc | 2013-11-22 10:18:30 -0800 | [diff] [blame] | 103 | |
| 104 | |
| 105 | .. class:: InvalidToken |
| 106 | |
| 107 | See :meth:`Fernet.decrypt` for more information. |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 108 | |
Alex Gaynor | b32b491 | 2014-01-23 16:24:13 -0600 | [diff] [blame] | 109 | Implementation |
| 110 | -------------- |
| 111 | |
| 112 | Fernet is built on top of a number of standard cryptographic primitives. |
| 113 | Specifically it uses: |
| 114 | |
| 115 | * :class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` in |
| 116 | :class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode with a |
| 117 | 128-bit key for encryption; using |
Alex Gaynor | 8e6b331 | 2014-06-30 11:39:27 -0700 | [diff] [blame] | 118 | :class:`~cryptography.hazmat.primitives.padding.PKCS7` padding. |
Alex Gaynor | b32b491 | 2014-01-23 16:24:13 -0600 | [diff] [blame] | 119 | * :class:`~cryptography.hazmat.primitives.hmac.HMAC` using |
| 120 | :class:`~cryptography.hazmat.primitives.hashes.SHA256` for authentication. |
| 121 | * Initialization vectors are generated using ``os.urandom()``. |
| 122 | |
| 123 | For complete details consult the `specification`_. |
| 124 | |
Alex Gaynor | 333fb10 | 2013-10-31 10:27:35 -0700 | [diff] [blame] | 125 | |
| 126 | .. _`Fernet`: https://github.com/fernet/spec/ |
Alex Gaynor | b32b491 | 2014-01-23 16:24:13 -0600 | [diff] [blame] | 127 | .. _`specification`: https://github.com/fernet/spec/blob/master/Spec.md |