You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
835 lines
32 KiB
835 lines
32 KiB
.. hazmat:: /fernet
|
|
|
|
|
|
Symmetric encryption
|
|
====================
|
|
|
|
.. module:: cryptography.hazmat.primitives.ciphers
|
|
|
|
Symmetric encryption is a way to `encrypt`_ or hide the contents of material
|
|
where the sender and receiver both use the same secret key. Note that symmetric
|
|
encryption is **not** sufficient for most applications because it only
|
|
provides secrecy but not authenticity. That means an attacker can't see the
|
|
message but an attacker can create bogus messages and force the application to
|
|
decrypt them.
|
|
|
|
For this reason it is **strongly** recommended to combine encryption with a
|
|
message authentication code, such as :doc:`HMAC </hazmat/primitives/mac/hmac>`,
|
|
in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
|
|
``cryptography`` includes a recipe named :doc:`/fernet` that does this for you.
|
|
**To minimize the risk of security issues you should evaluate Fernet to see if
|
|
it fits your needs before implementing anything using this module.**
|
|
|
|
.. class:: Cipher(algorithm, mode, backend)
|
|
|
|
Cipher objects combine an algorithm such as
|
|
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES` with a
|
|
mode like
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` or
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.CTR`. A simple
|
|
example of encrypting and then decrypting content with AES is:
|
|
|
|
.. doctest::
|
|
|
|
>>> import os
|
|
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
>>> from cryptography.hazmat.backends import default_backend
|
|
>>> backend = default_backend()
|
|
>>> key = os.urandom(32)
|
|
>>> iv = os.urandom(16)
|
|
>>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
|
|
>>> encryptor = cipher.encryptor()
|
|
>>> ct = encryptor.update(b"a secret message") + encryptor.finalize()
|
|
>>> decryptor = cipher.decryptor()
|
|
>>> decryptor.update(ct) + decryptor.finalize()
|
|
b'a secret message'
|
|
|
|
:param algorithms: A
|
|
:class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
|
|
instance such as those described
|
|
:ref:`below <symmetric-encryption-algorithms>`.
|
|
:param mode: A :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`
|
|
instance such as those described
|
|
:ref:`below <symmetric-encryption-modes>`.
|
|
:param backend: A
|
|
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
|
|
instance.
|
|
|
|
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
|
|
provided ``backend`` does not implement
|
|
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
|
|
|
|
.. method:: encryptor()
|
|
|
|
:return: An encrypting
|
|
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
|
|
instance.
|
|
|
|
If the backend doesn't support the requested combination of ``cipher``
|
|
and ``mode`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm`
|
|
exception will be raised.
|
|
|
|
.. method:: decryptor()
|
|
|
|
:return: A decrypting
|
|
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
|
|
instance.
|
|
|
|
If the backend doesn't support the requested combination of ``cipher``
|
|
and ``mode`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm`
|
|
exception will be raised.
|
|
|
|
.. _symmetric-encryption-algorithms:
|
|
|
|
Algorithms
|
|
~~~~~~~~~~
|
|
|
|
.. currentmodule:: cryptography.hazmat.primitives.ciphers.algorithms
|
|
|
|
.. class:: AES(key)
|
|
|
|
AES (Advanced Encryption Standard) is a block cipher standardized by NIST.
|
|
AES is both fast, and cryptographically strong. It is a good default
|
|
choice for encryption.
|
|
|
|
:param key: The secret key. This must be kept secret. Either ``128``,
|
|
``192``, or ``256`` :term:`bits` long.
|
|
:type key: :term:`bytes-like`
|
|
|
|
.. class:: Camellia(key)
|
|
|
|
Camellia is a block cipher approved for use by `CRYPTREC`_ and ISO/IEC.
|
|
It is considered to have comparable security and performance to AES but
|
|
is not as widely studied or deployed.
|
|
|
|
:param key: The secret key. This must be kept secret. Either ``128``,
|
|
``192``, or ``256`` :term:`bits` long.
|
|
:type key: :term:`bytes-like`
|
|
|
|
.. class:: ChaCha20(key)
|
|
|
|
.. versionadded:: 2.1
|
|
|
|
.. note::
|
|
|
|
In most cases users should use
|
|
:class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
|
|
instead of this class. `ChaCha20` alone does not provide integrity
|
|
so it must be combined with a MAC to be secure.
|
|
:class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305`
|
|
does this for you.
|
|
|
|
ChaCha20 is a stream cipher used in several IETF protocols. It is
|
|
standardized in :rfc:`7539`.
|
|
|
|
:param key: The secret key. This must be kept secret. ``256``
|
|
:term:`bits` (32 bytes) in length.
|
|
:type key: :term:`bytes-like`
|
|
|
|
:param nonce: Should be unique, a :term:`nonce`. It is
|
|
critical to never reuse a ``nonce`` with a given key. Any reuse of a
|
|
nonce with the same key compromises the security of every message
|
|
encrypted with that key. The nonce does not need to be kept secret
|
|
and may be included with the ciphertext. This must be ``128``
|
|
:term:`bits` in length.
|
|
:type nonce: :term:`bytes-like`
|
|
|
|
.. note::
|
|
|
|
In :rfc:`7539` the nonce is defined as a 96-bit value that is later
|
|
concatenated with a block counter (encoded as a 32-bit
|
|
little-endian). If you have a separate nonce and block counter
|
|
you will need to concatenate it yourself before passing it. For
|
|
example, if you have an initial block counter of 2 and a 96-bit
|
|
nonce the concatenated nonce would be
|
|
``struct.pack("<i", 2) + nonce``.
|
|
|
|
.. doctest::
|
|
|
|
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
>>> from cryptography.hazmat.backends import default_backend
|
|
>>> nonce = os.urandom(16)
|
|
>>> algorithm = algorithms.ChaCha20(key, nonce)
|
|
>>> cipher = Cipher(algorithm, mode=None, backend=default_backend())
|
|
>>> encryptor = cipher.encryptor()
|
|
>>> ct = encryptor.update(b"a secret message")
|
|
>>> decryptor = cipher.decryptor()
|
|
>>> decryptor.update(ct)
|
|
b'a secret message'
|
|
|
|
.. class:: TripleDES(key)
|
|
|
|
Triple DES (Data Encryption Standard), sometimes referred to as 3DES, is a
|
|
block cipher standardized by NIST. Triple DES has known crypto-analytic
|
|
flaws, however none of them currently enable a practical attack.
|
|
Nonetheless, Triple DES is not recommended for new applications because it
|
|
is incredibly slow; old applications should consider moving away from it.
|
|
|
|
:param key: The secret key. This must be kept secret. Either ``64``,
|
|
``128``, or ``192`` :term:`bits` long. DES only uses ``56``, ``112``,
|
|
or ``168`` bits of the key as there is a parity byte in each component
|
|
of the key. Some writing refers to there being up to three separate
|
|
keys that are each ``56`` bits long, they can simply be concatenated
|
|
to produce the full key.
|
|
:type key: :term:`bytes-like`
|
|
|
|
.. class:: CAST5(key)
|
|
|
|
.. versionadded:: 0.2
|
|
|
|
CAST5 (also known as CAST-128) is a block cipher approved for use in the
|
|
Canadian government by the `Communications Security Establishment`_. It is
|
|
a variable key length cipher and supports keys from 40-128 :term:`bits` in
|
|
length.
|
|
|
|
:param key: The secret key, This must be kept secret. 40 to 128
|
|
:term:`bits` in length in increments of 8 bits.
|
|
:type key: :term:`bytes-like`
|
|
|
|
.. class:: SEED(key)
|
|
|
|
.. versionadded:: 0.4
|
|
|
|
SEED is a block cipher developed by the Korea Information Security Agency
|
|
(KISA). It is defined in :rfc:`4269` and is used broadly throughout South
|
|
Korean industry, but rarely found elsewhere.
|
|
|
|
:param key: The secret key. This must be kept secret. ``128``
|
|
:term:`bits` in length.
|
|
:type key: :term:`bytes-like`
|
|
|
|
Weak ciphers
|
|
------------
|
|
|
|
.. warning::
|
|
|
|
These ciphers are considered weak for a variety of reasons. New
|
|
applications should avoid their use and existing applications should
|
|
strongly consider migrating away.
|
|
|
|
.. class:: Blowfish(key)
|
|
|
|
Blowfish is a block cipher developed by Bruce Schneier. It is known to be
|
|
susceptible to attacks when using weak keys. The author has recommended
|
|
that users of Blowfish move to newer algorithms such as :class:`AES`.
|
|
|
|
:param key: The secret key. This must be kept secret. 32 to 448
|
|
:term:`bits` in length in increments of 8 bits.
|
|
:type key: :term:`bytes-like`
|
|
|
|
.. class:: ARC4(key)
|
|
|
|
ARC4 (Alleged RC4) is a stream cipher with serious weaknesses in its
|
|
initial stream output. Its use is strongly discouraged. ARC4 does not use
|
|
mode constructions.
|
|
|
|
:param key: The secret key. This must be kept secret. Either ``40``,
|
|
``56``, ``64``, ``80``, ``128``, ``192``, or ``256`` :term:`bits` in
|
|
length.
|
|
:type key: :term:`bytes-like`
|
|
|
|
.. doctest::
|
|
|
|
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
>>> from cryptography.hazmat.backends import default_backend
|
|
>>> algorithm = algorithms.ARC4(key)
|
|
>>> cipher = Cipher(algorithm, mode=None, backend=default_backend())
|
|
>>> encryptor = cipher.encryptor()
|
|
>>> ct = encryptor.update(b"a secret message")
|
|
>>> decryptor = cipher.decryptor()
|
|
>>> decryptor.update(ct)
|
|
b'a secret message'
|
|
|
|
.. class:: IDEA(key)
|
|
|
|
IDEA (`International Data Encryption Algorithm`_) is a block cipher created
|
|
in 1991. It is an optional component of the `OpenPGP`_ standard. This cipher
|
|
is susceptible to attacks when using weak keys. It is recommended that you
|
|
do not use this cipher for new applications.
|
|
|
|
:param key: The secret key. This must be kept secret. ``128``
|
|
:term:`bits` in length.
|
|
:type key: :term:`bytes-like`
|
|
|
|
|
|
.. _symmetric-encryption-modes:
|
|
|
|
Modes
|
|
~~~~~
|
|
|
|
.. module:: cryptography.hazmat.primitives.ciphers.modes
|
|
|
|
.. class:: CBC(initialization_vector)
|
|
|
|
CBC (Cipher Block Chaining) is a mode of operation for block ciphers. It is
|
|
considered cryptographically strong.
|
|
|
|
**Padding is required when using this mode.**
|
|
|
|
:param initialization_vector: Must be :doc:`random bytes
|
|
</random-numbers>`. They do not need to be kept secret and they can be
|
|
included in a transmitted message. Must be the same number of bytes as
|
|
the ``block_size`` of the cipher. Each time something is encrypted a
|
|
new ``initialization_vector`` should be generated. Do not reuse an
|
|
``initialization_vector`` with a given ``key``, and particularly do not
|
|
use a constant ``initialization_vector``.
|
|
:type initialization_vector: :term:`bytes-like`
|
|
|
|
A good construction looks like:
|
|
|
|
.. doctest::
|
|
|
|
>>> import os
|
|
>>> from cryptography.hazmat.primitives.ciphers.modes import CBC
|
|
>>> iv = os.urandom(16)
|
|
>>> mode = CBC(iv)
|
|
|
|
While the following is bad and will leak information:
|
|
|
|
.. doctest::
|
|
|
|
>>> from cryptography.hazmat.primitives.ciphers.modes import CBC
|
|
>>> iv = b"a" * 16
|
|
>>> mode = CBC(iv)
|
|
|
|
|
|
.. class:: CTR(nonce)
|
|
|
|
.. warning::
|
|
|
|
Counter mode is not recommended for use with block ciphers that have a
|
|
block size of less than 128-:term:`bits`.
|
|
|
|
CTR (Counter) is a mode of operation for block ciphers. It is considered
|
|
cryptographically strong. It transforms a block cipher into a stream
|
|
cipher.
|
|
|
|
**This mode does not require padding.**
|
|
|
|
:param nonce: Should be unique, a :term:`nonce`. It is
|
|
critical to never reuse a ``nonce`` with a given key. Any reuse of a
|
|
nonce with the same key compromises the security of every message
|
|
encrypted with that key. Must be the same number of bytes as the
|
|
``block_size`` of the cipher with a given key. The nonce does not need
|
|
to be kept secret and may be included with the ciphertext.
|
|
:type nonce: :term:`bytes-like`
|
|
|
|
.. class:: OFB(initialization_vector)
|
|
|
|
OFB (Output Feedback) is a mode of operation for block ciphers. It
|
|
transforms a block cipher into a stream cipher.
|
|
|
|
**This mode does not require padding.**
|
|
|
|
:param initialization_vector: Must be :doc:`random bytes
|
|
</random-numbers>`. They do not need to be kept secret and they can be
|
|
included in a transmitted message. Must be the same number of bytes as
|
|
the ``block_size`` of the cipher. Do not reuse an
|
|
``initialization_vector`` with a given ``key``.
|
|
:type initialization_vector: :term:`bytes-like`
|
|
|
|
.. class:: CFB(initialization_vector)
|
|
|
|
CFB (Cipher Feedback) is a mode of operation for block ciphers. It
|
|
transforms a block cipher into a stream cipher.
|
|
|
|
**This mode does not require padding.**
|
|
|
|
:param initialization_vector: Must be :doc:`random bytes
|
|
</random-numbers>`. They do not need to be kept secret and they can be
|
|
included in a transmitted message. Must be the same number of bytes as
|
|
the ``block_size`` of the cipher. Do not reuse an
|
|
``initialization_vector`` with a given ``key``.
|
|
:type initialization_vector: :term:`bytes-like`
|
|
|
|
.. class:: CFB8(initialization_vector)
|
|
|
|
CFB (Cipher Feedback) is a mode of operation for block ciphers. It
|
|
transforms a block cipher into a stream cipher. The CFB8 variant uses an
|
|
8-bit shift register.
|
|
|
|
**This mode does not require padding.**
|
|
|
|
:param initialization_vector: Must be :doc:`random bytes
|
|
</random-numbers>`. They do not need to be kept secret and they can be
|
|
included in a transmitted message. Must be the same number of bytes as
|
|
the ``block_size`` of the cipher. Do not reuse an
|
|
``initialization_vector`` with a given ``key``.
|
|
:type initialization_vector: :term:`bytes-like`
|
|
|
|
.. class:: GCM(initialization_vector, tag=None, min_tag_length=16)
|
|
|
|
.. danger::
|
|
|
|
If you are encrypting data that can fit into memory you should strongly
|
|
consider using
|
|
:class:`~cryptography.hazmat.primitives.ciphers.aead.AESGCM` instead
|
|
of this.
|
|
|
|
When using this mode you **must** not use the decrypted data until
|
|
the appropriate finalization method
|
|
(:meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.finalize`
|
|
or
|
|
:meth:`~cryptography.hazmat.primitives.ciphers.AEADDecryptionContext.finalize_with_tag`)
|
|
has been called. GCM provides **no** guarantees of ciphertext integrity
|
|
until decryption is complete.
|
|
|
|
GCM (Galois Counter Mode) is a mode of operation for block ciphers. An
|
|
AEAD (authenticated encryption with additional data) mode is a type of
|
|
block cipher mode that simultaneously encrypts the message as well as
|
|
authenticating it. Additional unencrypted data may also be authenticated.
|
|
Additional means of verifying integrity such as
|
|
:doc:`HMAC </hazmat/primitives/mac/hmac>` are not necessary.
|
|
|
|
**This mode does not require padding.**
|
|
|
|
:param initialization_vector: Must be unique, a :term:`nonce`.
|
|
They do not need to be kept secret and they can be included in a
|
|
transmitted message. NIST `recommends a 96-bit IV length`_ for
|
|
performance critical situations but it can be up to 2\ :sup:`64` - 1
|
|
:term:`bits`. Do not reuse an ``initialization_vector`` with a given
|
|
``key``.
|
|
:type initialization_vector: :term:`bytes-like`
|
|
|
|
.. note::
|
|
|
|
Cryptography will generate a 128-bit tag when finalizing encryption.
|
|
You can shorten a tag by truncating it to the desired length but this
|
|
is **not recommended** as it makes it easier to forge messages, and
|
|
also potentially leaks the key (`NIST SP-800-38D`_ recommends
|
|
96-:term:`bits` or greater). Applications wishing to allow truncation
|
|
can pass the ``min_tag_length`` parameter.
|
|
|
|
.. versionchanged:: 0.5
|
|
|
|
The ``min_tag_length`` parameter was added in ``0.5``, previously
|
|
truncation down to ``4`` bytes was always allowed.
|
|
|
|
:param bytes tag: The tag bytes to verify during decryption. When
|
|
encrypting this must be ``None``. When decrypting, it may be ``None``
|
|
if the tag is supplied on finalization using
|
|
:meth:`~cryptography.hazmat.primitives.ciphers.AEADDecryptionContext.finalize_with_tag`.
|
|
Otherwise, the tag is mandatory.
|
|
|
|
:param int min_tag_length: The minimum length ``tag`` must be. By default
|
|
this is ``16``, meaning tag truncation is not allowed. Allowing tag
|
|
truncation is strongly discouraged for most applications.
|
|
|
|
:raises ValueError: This is raised if ``len(tag) < min_tag_length`` or the
|
|
``initialization_vector`` is too short.
|
|
|
|
:raises NotImplementedError: This is raised if the version of the OpenSSL
|
|
backend used is 1.0.1 or earlier.
|
|
|
|
An example of securely encrypting and decrypting data with ``AES`` in the
|
|
``GCM`` mode looks like:
|
|
|
|
.. testcode::
|
|
|
|
import os
|
|
|
|
from cryptography.hazmat.backends import default_backend
|
|
from cryptography.hazmat.primitives.ciphers import (
|
|
Cipher, algorithms, modes
|
|
)
|
|
|
|
def encrypt(key, plaintext, associated_data):
|
|
# Generate a random 96-bit IV.
|
|
iv = os.urandom(12)
|
|
|
|
# Construct an AES-GCM Cipher object with the given key and a
|
|
# randomly generated IV.
|
|
encryptor = Cipher(
|
|
algorithms.AES(key),
|
|
modes.GCM(iv),
|
|
backend=default_backend()
|
|
).encryptor()
|
|
|
|
# associated_data will be authenticated but not encrypted,
|
|
# it must also be passed in on decryption.
|
|
encryptor.authenticate_additional_data(associated_data)
|
|
|
|
# Encrypt the plaintext and get the associated ciphertext.
|
|
# GCM does not require padding.
|
|
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
|
|
|
|
return (iv, ciphertext, encryptor.tag)
|
|
|
|
def decrypt(key, associated_data, iv, ciphertext, tag):
|
|
# Construct a Cipher object, with the key, iv, and additionally the
|
|
# GCM tag used for authenticating the message.
|
|
decryptor = Cipher(
|
|
algorithms.AES(key),
|
|
modes.GCM(iv, tag),
|
|
backend=default_backend()
|
|
).decryptor()
|
|
|
|
# We put associated_data back in or the tag will fail to verify
|
|
# when we finalize the decryptor.
|
|
decryptor.authenticate_additional_data(associated_data)
|
|
|
|
# Decryption gets us the authenticated plaintext.
|
|
# If the tag does not match an InvalidTag exception will be raised.
|
|
return decryptor.update(ciphertext) + decryptor.finalize()
|
|
|
|
iv, ciphertext, tag = encrypt(
|
|
key,
|
|
b"a secret message!",
|
|
b"authenticated but not encrypted payload"
|
|
)
|
|
|
|
print(decrypt(
|
|
key,
|
|
b"authenticated but not encrypted payload",
|
|
iv,
|
|
ciphertext,
|
|
tag
|
|
))
|
|
|
|
.. testoutput::
|
|
|
|
b'a secret message!'
|
|
|
|
.. class:: XTS(tweak)
|
|
|
|
.. versionadded:: 2.1
|
|
|
|
.. warning::
|
|
|
|
XTS mode is meant for disk encryption and should not be used in other
|
|
contexts. ``cryptography`` only supports XTS mode with
|
|
:class:`~cryptography.hazmat.primitives.ciphers.algorithms.AES`.
|
|
|
|
.. note::
|
|
|
|
AES XTS keys are double length. This means that to do AES-128
|
|
encryption in XTS mode you need a 256-bit key. Similarly, AES-256
|
|
requires passing a 512-bit key. AES 192 is not supported in XTS mode.
|
|
|
|
XTS (XEX-based tweaked-codebook mode with ciphertext stealing) is a mode
|
|
of operation for the AES block cipher that is used for `disk encryption`_.
|
|
|
|
**This mode does not require padding.**
|
|
|
|
:param tweak: The tweak is a 16 byte value typically derived from
|
|
something like the disk sector number. A given ``(tweak, key)`` pair
|
|
should not be reused, although doing so is less catastrophic than
|
|
in CTR mode.
|
|
:type tweak: :term:`bytes-like`
|
|
|
|
Insecure modes
|
|
--------------
|
|
|
|
.. warning::
|
|
|
|
These modes are insecure. New applications should never make use of them,
|
|
and existing applications should strongly consider migrating away.
|
|
|
|
|
|
.. class:: ECB()
|
|
|
|
ECB (Electronic Code Book) is the simplest mode of operation for block
|
|
ciphers. Each block of data is encrypted in the same way. This means
|
|
identical plaintext blocks will always result in identical ciphertext
|
|
blocks, which can leave `significant patterns in the output`_.
|
|
|
|
**Padding is required when using this mode.**
|
|
|
|
Interfaces
|
|
~~~~~~~~~~
|
|
|
|
.. currentmodule:: cryptography.hazmat.primitives.ciphers
|
|
|
|
.. class:: CipherContext
|
|
|
|
When calling ``encryptor()`` or ``decryptor()`` on a ``Cipher`` object
|
|
the result will conform to the ``CipherContext`` interface. You can then
|
|
call ``update(data)`` with data until you have fed everything into the
|
|
context. Once that is done call ``finalize()`` to finish the operation and
|
|
obtain the remainder of the data.
|
|
|
|
Block ciphers require that the plaintext or ciphertext always be a multiple
|
|
of their block size. Because of that **padding** is sometimes required to
|
|
make a message the correct size. ``CipherContext`` will not automatically
|
|
apply any padding; you'll need to add your own. For block ciphers the
|
|
recommended padding is
|
|
:class:`~cryptography.hazmat.primitives.padding.PKCS7`. If you are using a
|
|
stream cipher mode (such as
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.CTR`) you don't have
|
|
to worry about this.
|
|
|
|
.. method:: update(data)
|
|
|
|
:param data: The data you wish to pass into the context.
|
|
:type data: :term:`bytes-like`
|
|
:return bytes: Returns the data that was encrypted or decrypted.
|
|
:raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize`
|
|
|
|
When the ``Cipher`` was constructed in a mode that turns it into a
|
|
stream cipher (e.g.
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.CTR`), this will
|
|
return bytes immediately, however in other modes it will return chunks
|
|
whose size is determined by the cipher's block size.
|
|
|
|
.. method:: update_into(data, buf)
|
|
|
|
.. versionadded:: 1.8
|
|
|
|
.. warning::
|
|
|
|
This method allows you to avoid a memory copy by passing a writable
|
|
buffer and reading the resulting data. You are responsible for
|
|
correctly sizing the buffer and properly handling the data. This
|
|
method should only be used when extremely high performance is a
|
|
requirement and you will be making many small calls to
|
|
``update_into``.
|
|
|
|
:param data: The data you wish to pass into the context.
|
|
:type data: :term:`bytes-like`
|
|
:param buf: A writable Python buffer that the data will be written
|
|
into. This buffer should be ``len(data) + n - 1`` bytes where ``n``
|
|
is the block size (in bytes) of the cipher and mode combination.
|
|
:return int: Number of bytes written.
|
|
:raises NotImplementedError: This is raised if the version of ``cffi``
|
|
used is too old (this can happen on older PyPy releases).
|
|
:raises ValueError: This is raised if the supplied buffer is too small.
|
|
|
|
.. doctest::
|
|
|
|
>>> import os
|
|
>>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
>>> from cryptography.hazmat.backends import default_backend
|
|
>>> backend = default_backend()
|
|
>>> key = os.urandom(32)
|
|
>>> iv = os.urandom(16)
|
|
>>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend)
|
|
>>> encryptor = cipher.encryptor()
|
|
>>> # the buffer needs to be at least len(data) + n - 1 where n is cipher/mode block size in bytes
|
|
>>> buf = bytearray(31)
|
|
>>> len_encrypted = encryptor.update_into(b"a secret message", buf)
|
|
>>> # get the ciphertext from the buffer reading only the bytes written to it (len_encrypted)
|
|
>>> ct = bytes(buf[:len_encrypted]) + encryptor.finalize()
|
|
>>> decryptor = cipher.decryptor()
|
|
>>> len_decrypted = decryptor.update_into(ct, buf)
|
|
>>> # get the plaintext from the buffer reading only the bytes written (len_decrypted)
|
|
>>> bytes(buf[:len_decrypted]) + decryptor.finalize()
|
|
b'a secret message'
|
|
|
|
.. method:: finalize()
|
|
|
|
:return bytes: Returns the remainder of the data.
|
|
:raises ValueError: This is raised when the data provided isn't
|
|
a multiple of the algorithm's block size.
|
|
|
|
Once ``finalize`` is called this object can no longer be used and
|
|
:meth:`update` and :meth:`finalize` will raise an
|
|
:class:`~cryptography.exceptions.AlreadyFinalized` exception.
|
|
|
|
.. class:: AEADCipherContext
|
|
|
|
When calling ``encryptor`` or ``decryptor`` on a ``Cipher`` object
|
|
with an AEAD mode (e.g.
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.GCM`) the result will
|
|
conform to the ``AEADCipherContext`` and ``CipherContext`` interfaces. If
|
|
it is an encryption or decryption context it will additionally be an
|
|
``AEADEncryptionContext`` or ``AEADDecryptionContext`` instance,
|
|
respectively. ``AEADCipherContext`` contains an additional method
|
|
:meth:`authenticate_additional_data` for adding additional authenticated
|
|
but unencrypted data (see note below). You should call this before calls to
|
|
``update``. When you are done call ``finalize`` to finish the operation.
|
|
|
|
.. note::
|
|
|
|
In AEAD modes all data passed to ``update()`` will be both encrypted
|
|
and authenticated. Do not pass encrypted data to the
|
|
``authenticate_additional_data()`` method. It is meant solely for
|
|
additional data you may want to authenticate but leave unencrypted.
|
|
|
|
.. method:: authenticate_additional_data(data)
|
|
|
|
:param data: Any data you wish to authenticate but not encrypt.
|
|
:type data: :term:`bytes-like`
|
|
:raises: :class:`~cryptography.exceptions.AlreadyFinalized`
|
|
|
|
.. class:: AEADEncryptionContext
|
|
|
|
When creating an encryption context using ``encryptor`` on a ``Cipher``
|
|
object with an AEAD mode such as
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` an object
|
|
conforming to both the ``AEADEncryptionContext`` and ``AEADCipherContext``
|
|
interfaces will be returned. This interface provides one
|
|
additional attribute ``tag``. ``tag`` can only be obtained after
|
|
``finalize`` has been called.
|
|
|
|
.. attribute:: tag
|
|
|
|
:return bytes: Returns the tag value as bytes.
|
|
:raises: :class:`~cryptography.exceptions.NotYetFinalized` if called
|
|
before the context is finalized.
|
|
|
|
.. class:: AEADDecryptionContext
|
|
|
|
.. versionadded:: 1.9
|
|
|
|
When creating an encryption context using ``decryptor`` on a ``Cipher``
|
|
object with an AEAD mode such as
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` an object
|
|
conforming to both the ``AEADDecryptionContext`` and ``AEADCipherContext``
|
|
interfaces will be returned. This interface provides one additional method
|
|
:meth:`finalize_with_tag` that allows passing the authentication tag for
|
|
validation after the ciphertext has been decrypted.
|
|
|
|
.. method:: finalize_with_tag(tag)
|
|
|
|
.. note::
|
|
|
|
This method is not supported when compiled against OpenSSL 1.0.1.
|
|
|
|
:param bytes tag: The tag bytes to verify after decryption.
|
|
:return bytes: Returns the remainder of the data.
|
|
:raises ValueError: This is raised when the data provided isn't
|
|
a multiple of the algorithm's block size, if ``min_tag_length`` is
|
|
less than 4, or if ``len(tag) < min_tag_length``.
|
|
``min_tag_length`` is an argument to the ``GCM`` constructor.
|
|
:raises NotImplementedError: This is raised if the version of the
|
|
OpenSSL backend used is 1.0.1 or earlier.
|
|
|
|
If the authentication tag was not already supplied to the constructor
|
|
of the :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` mode
|
|
object, this method must be used instead of
|
|
:meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.finalize`.
|
|
|
|
.. class:: CipherAlgorithm
|
|
|
|
A named symmetric encryption algorithm.
|
|
|
|
.. attribute:: name
|
|
|
|
:type: str
|
|
|
|
The standard name for the mode, for example, "AES", "Camellia", or
|
|
"Blowfish".
|
|
|
|
.. attribute:: key_size
|
|
|
|
:type: int
|
|
|
|
The number of :term:`bits` in the key being used.
|
|
|
|
|
|
.. class:: BlockCipherAlgorithm
|
|
|
|
A block cipher algorithm.
|
|
|
|
.. attribute:: block_size
|
|
|
|
:type: int
|
|
|
|
The number of :term:`bits` in a block.
|
|
|
|
Interfaces used by the symmetric cipher modes described in
|
|
:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
|
|
|
|
.. currentmodule:: cryptography.hazmat.primitives.ciphers.modes
|
|
|
|
.. class:: Mode
|
|
|
|
A named cipher mode.
|
|
|
|
.. attribute:: name
|
|
|
|
:type: str
|
|
|
|
This should be the standard shorthand name for the mode, for example
|
|
Cipher-Block Chaining mode is "CBC".
|
|
|
|
The name may be used by a backend to influence the operation of a
|
|
cipher in conjunction with the algorithm's name.
|
|
|
|
.. method:: validate_for_algorithm(algorithm)
|
|
|
|
:param cryptography.hazmat.primitives.ciphers.CipherAlgorithm algorithm:
|
|
|
|
Checks that the combination of this mode with the provided algorithm
|
|
meets any necessary invariants. This should raise an exception if they
|
|
are not met.
|
|
|
|
For example, the
|
|
:class:`~cryptography.hazmat.primitives.ciphers.modes.CBC` mode uses
|
|
this method to check that the provided initialization vector's length
|
|
matches the block size of the algorithm.
|
|
|
|
|
|
.. class:: ModeWithInitializationVector
|
|
|
|
A cipher mode with an initialization vector.
|
|
|
|
.. attribute:: initialization_vector
|
|
|
|
:type: :term:`bytes-like`
|
|
|
|
Exact requirements of the initialization are described by the
|
|
documentation of individual modes.
|
|
|
|
|
|
.. class:: ModeWithNonce
|
|
|
|
A cipher mode with a nonce.
|
|
|
|
.. attribute:: nonce
|
|
|
|
:type: :term:`bytes-like`
|
|
|
|
Exact requirements of the nonce are described by the documentation of
|
|
individual modes.
|
|
|
|
|
|
.. class:: ModeWithAuthenticationTag
|
|
|
|
A cipher mode with an authentication tag.
|
|
|
|
.. attribute:: tag
|
|
|
|
:type: :term:`bytes-like`
|
|
|
|
Exact requirements of the tag are described by the documentation of
|
|
individual modes.
|
|
|
|
|
|
.. class:: ModeWithTweak
|
|
|
|
.. versionadded:: 2.1
|
|
|
|
A cipher mode with a tweak.
|
|
|
|
.. attribute:: tweak
|
|
|
|
:type: :term:`bytes-like`
|
|
|
|
Exact requirements of the tweak are described by the documentation of
|
|
individual modes.
|
|
|
|
Exceptions
|
|
~~~~~~~~~~
|
|
|
|
.. currentmodule:: cryptography.exceptions
|
|
|
|
|
|
.. class:: InvalidTag
|
|
|
|
This is raised if an authenticated encryption tag fails to verify during
|
|
decryption.
|
|
|
|
|
|
|
|
.. _`described by Colin Percival`: https://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
|
|
.. _`recommends a 96-bit IV length`: https://csrc.nist.gov/publications/detail/sp/800-38d/final
|
|
.. _`NIST SP-800-38D`: https://csrc.nist.gov/publications/detail/sp/800-38d/final
|
|
.. _`Communications Security Establishment`: https://www.cse-cst.gc.ca
|
|
.. _`encrypt`: https://ssd.eff.org/en/module/what-should-i-know-about-encryption
|
|
.. _`CRYPTREC`: https://www.cryptrec.go.jp/english/
|
|
.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29
|
|
.. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
|
|
.. _`OpenPGP`: https://www.openpgp.org/
|
|
.. _`disk encryption`: https://en.wikipedia.org/wiki/Disk_encryption_theory#XTS
|