aboutsummaryrefslogtreecommitdiffstats
path: root/docs/hazmat/primitives/symmetric-encryption.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/hazmat/primitives/symmetric-encryption.rst')
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst348
1 files changed, 280 insertions, 68 deletions
diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst
index 309c6fd0..46f0786d 100644
--- a/docs/hazmat/primitives/symmetric-encryption.rst
+++ b/docs/hazmat/primitives/symmetric-encryption.rst
@@ -16,6 +16,9 @@ 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)
@@ -39,18 +42,18 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
>>> ct = encryptor.update(b"a secret message") + encryptor.finalize()
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct) + decryptor.finalize()
- 'a secret message'
+ b'a secret message'
- :param algorithms: A
+ :param algorithm: A
:class:`~cryptography.hazmat.primitives.ciphers.CipherAlgorithm`
- provider such as those described
+ instance such as those described
:ref:`below <symmetric-encryption-algorithms>`.
:param mode: A :class:`~cryptography.hazmat.primitives.ciphers.modes.Mode`
- provider such as those described
+ instance such as those described
:ref:`below <symmetric-encryption-modes>`.
:param backend: A
:class:`~cryptography.hazmat.backends.interfaces.CipherBackend`
- provider.
+ instance.
:raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if the
provided ``backend`` does not implement
@@ -60,7 +63,7 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
:return: An encrypting
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
- provider.
+ instance.
If the backend doesn't support the requested combination of ``cipher``
and ``mode`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm`
@@ -70,7 +73,7 @@ in an "encrypt-then-MAC" formulation as `described by Colin Percival`_.
:return: A decrypting
:class:`~cryptography.hazmat.primitives.ciphers.CipherContext`
- provider.
+ instance.
If the backend doesn't support the requested combination of ``cipher``
and ``mode`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm`
@@ -89,8 +92,9 @@ Algorithms
AES is both fast, and cryptographically strong. It is a good default
choice for encryption.
- :param bytes key: The secret key. This must be kept secret. Either ``128``,
- ``192``, or ``256`` bits long.
+ :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)
@@ -98,22 +102,76 @@ Algorithms
It is considered to have comparable security and performance to AES but
is not as widely studied or deployed.
- :param bytes key: The secret key. This must be kept secret. Either ``128``,
- ``192``, or ``256`` bits long.
+ :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, Triples DES is not recommended for new applications because it
+ Nonetheless, Triple DES is not recommended for new applications because it
is incredibly slow; old applications should consider moving away from it.
- :param bytes key: The secret key. This must be kept secret. Either ``64``,
- ``128``, or ``192`` 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.
+ :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)
@@ -121,10 +179,12 @@ Algorithms
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 bits in length.
+ a variable key length cipher and supports keys from 40-128 :term:`bits` in
+ length.
- :param bytes key: The secret key, This must be kept secret. 40 to 128 bits
- in length in increments of 8 bits.
+ :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)
@@ -134,8 +194,9 @@ Algorithms
(KISA). It is defined in :rfc:`4269` and is used broadly throughout South
Korean industry, but rarely found elsewhere.
- :param bytes key: The secret key. This must be kept secret. ``128`` bits in
- length.
+ :param key: The secret key. This must be kept secret. ``128``
+ :term:`bits` in length.
+ :type key: :term:`bytes-like`
Weak ciphers
------------
@@ -152,8 +213,9 @@ Weak ciphers
susceptible to attacks when using weak keys. The author has recommended
that users of Blowfish move to newer algorithms such as :class:`AES`.
- :param bytes key: The secret key. This must be kept secret. 32 to 448 bits
- in length in increments of 8 bits.
+ :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)
@@ -161,8 +223,10 @@ Weak ciphers
initial stream output. Its use is strongly discouraged. ARC4 does not use
mode constructions.
- :param bytes key: The secret key. This must be kept secret. Either ``40``,
- ``56``, ``64``, ``80``, ``128``, ``192``, or ``256`` bits in length.
+ :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::
@@ -174,7 +238,7 @@ Weak ciphers
>>> ct = encryptor.update(b"a secret message")
>>> decryptor = cipher.decryptor()
>>> decryptor.update(ct)
- 'a secret message'
+ b'a secret message'
.. class:: IDEA(key)
@@ -183,8 +247,9 @@ Weak ciphers
is susceptible to attacks when using weak keys. It is recommended that you
do not use this cipher for new applications.
- :param bytes key: The secret key. This must be kept secret. ``128`` bits in
- length.
+ :param key: The secret key. This must be kept secret. ``128``
+ :term:`bits` in length.
+ :type key: :term:`bytes-like`
.. _symmetric-encryption-modes:
@@ -201,13 +266,14 @@ Modes
**Padding is required when using this mode.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :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:
@@ -223,7 +289,7 @@ Modes
.. doctest::
>>> from cryptography.hazmat.primitives.ciphers.modes import CBC
- >>> iv = "a" * 16
+ >>> iv = b"a" * 16
>>> mode = CBC(iv)
@@ -232,7 +298,7 @@ Modes
.. warning::
Counter mode is not recommended for use with block ciphers that have a
- block size of less than 128-bits.
+ 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
@@ -240,12 +306,13 @@ Modes
**This mode does not require padding.**
- :param bytes nonce: Should be unique, a :term:`nonce`. It is
+ :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)
@@ -254,11 +321,12 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :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)
@@ -267,11 +335,12 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :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)
@@ -281,18 +350,27 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be :doc:`random bytes
+ :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
- :meth:`~cryptography.hazmat.primitives.ciphers.CipherContext.finalize`
+ 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.
@@ -305,20 +383,22 @@ Modes
**This mode does not require padding.**
- :param bytes initialization_vector: Must be unique, a :term:`nonce`.
+ :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
- bits. Do not reuse an ``initialization_vector`` with a given ``key``.
+ :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 lowers the security margins of the
- authentication (`NIST SP-800-38D`_ recommends 96-bits or greater).
- Applications wishing to allow truncation must pass the
- ``min_tag_length`` parameter.
+ 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
@@ -326,18 +406,26 @@ Modes
truncation down to ``4`` bytes was always allowed.
:param bytes tag: The tag bytes to verify during decryption. When
- encrypting this must be ``None``.
+ 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 bytes min_tag_length: The minimum length ``tag`` must be. By default
+ :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``.
+ :raises ValueError: This is raised if ``len(tag) < min_tag_length`` or the
+ ``initialization_vector`` is too short.
+
+ 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
)
@@ -397,8 +485,34 @@ Modes
.. testoutput::
- a secret message!
+ 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
--------------
@@ -419,7 +533,7 @@ Insecure modes
**Padding is required when using this mode.**
Interfaces
-----------
+~~~~~~~~~~
.. currentmodule:: cryptography.hazmat.primitives.ciphers
@@ -443,7 +557,8 @@ Interfaces
.. method:: update(data)
- :param bytes data: The data you wish to pass into the context.
+ :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`
@@ -453,6 +568,50 @@ Interfaces
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.
@@ -469,12 +628,12 @@ Interfaces
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 context it will additionally be an
- ``AEADEncryptionContext`` provider. ``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.
+ 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::
@@ -485,7 +644,8 @@ Interfaces
.. method:: authenticate_additional_data(data)
- :param bytes data: Any data you wish to authenticate but not encrypt.
+ :param data: Any data you wish to authenticate but not encrypt.
+ :type data: :term:`bytes-like`
:raises: :class:`~cryptography.exceptions.AlreadyFinalized`
.. class:: AEADEncryptionContext
@@ -504,6 +664,32 @@ Interfaces
: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)
+
+ :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.
+
+ 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.
@@ -519,7 +705,7 @@ Interfaces
:type: int
- The number of bits in the key being used.
+ The number of :term:`bits` in the key being used.
.. class:: BlockCipherAlgorithm
@@ -530,7 +716,7 @@ Interfaces
:type: int
- The number of bits in a block.
+ The number of :term:`bits` in a block.
Interfaces used by the symmetric cipher modes described in
:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.
@@ -571,7 +757,7 @@ Interfaces used by the symmetric cipher modes described in
.. attribute:: initialization_vector
- :type: bytes
+ :type: :term:`bytes-like`
Exact requirements of the initialization are described by the
documentation of individual modes.
@@ -583,7 +769,7 @@ Interfaces used by the symmetric cipher modes described in
.. attribute:: nonce
- :type: bytes
+ :type: :term:`bytes-like`
Exact requirements of the nonce are described by the documentation of
individual modes.
@@ -595,19 +781,45 @@ Interfaces used by the symmetric cipher modes described in
.. attribute:: tag
- :type: bytes
+ :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`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html
-.. _`recommends a 96-bit IV length`: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
-.. _`NIST SP-800-38D`: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
+.. _`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-encryption
-.. _`CRYPTREC`: http://www.cryptrec.go.jp/english/
-.. _`significant patterns in the output`: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29
+.. _`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_(ECB)
.. _`International Data Encryption Algorithm`: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
-.. _`OpenPGP`: http://www.openpgp.org
+.. _`OpenPGP`: https://www.openpgp.org/
+.. _`disk encryption`: https://en.wikipedia.org/wiki/Disk_encryption_theory#XTS