diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2013-12-15 23:09:13 -0800 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2013-12-15 23:09:13 -0800 |
commit | 5175e4e6394ade40e38dc00b8e1e14a2877aafe4 (patch) | |
tree | ce9073684c790f908044f939e92312ad82112514 /docs/hazmat/primitives | |
parent | 973499aded3ce3580a8c6d44aa111288240f90a1 (diff) | |
parent | ffb7726fa3042e66e8011fbd17a8b6f83f0c8110 (diff) | |
download | cryptography-5175e4e6394ade40e38dc00b8e1e14a2877aafe4.tar.gz cryptography-5175e4e6394ade40e38dc00b8e1e14a2877aafe4.tar.bz2 cryptography-5175e4e6394ade40e38dc00b8e1e14a2877aafe4.zip |
Merge branch 'master' into validate-iv
Conflicts:
cryptography/hazmat/primitives/ciphers/modes.py
tests/hazmat/primitives/test_block.py
Diffstat (limited to 'docs/hazmat/primitives')
-rw-r--r-- | docs/hazmat/primitives/constant-time.rst | 38 | ||||
-rw-r--r-- | docs/hazmat/primitives/cryptographic-hashes.rst | 4 | ||||
-rw-r--r-- | docs/hazmat/primitives/hmac.rst | 4 | ||||
-rw-r--r-- | docs/hazmat/primitives/index.rst | 1 | ||||
-rw-r--r-- | docs/hazmat/primitives/symmetric-encryption.rst | 92 |
5 files changed, 127 insertions, 12 deletions
diff --git a/docs/hazmat/primitives/constant-time.rst b/docs/hazmat/primitives/constant-time.rst new file mode 100644 index 00000000..632e7c68 --- /dev/null +++ b/docs/hazmat/primitives/constant-time.rst @@ -0,0 +1,38 @@ +.. hazmat:: + +Constant time functions +======================= + +.. currentmodule:: cryptography.hazmat.primitives.constant_time + +This module contains functions for operating with secret data in a way that +does not leak information about that data through how long it takes to perform +the operation. These functions should be used whenever operating on secret data +along with data that is user supplied. + +An example would be comparing a HMAC signature received from a client to the +one generated by the server code for authentication purposes. + +For more information about this sort of issue, see `Coda Hale's blog post`_ +about the timing attacks on KeyCzar and Java's ``MessageDigest.isEqual()``. + + +.. function:: bytes_eq(a, b) + + Compare ``a`` and ``b`` to one another in constant time if they are of the + same length. + + .. doctest:: + + >>> from cryptography.hazmat.primitives import constant_time + >>> constant_time.bytes_eq(b"foo", b"foo") + True + >>> constant_time.bytes_eq(b"foo", b"bar") + False + + :param a bytes: The left-hand side. + :param b bytes: The right-hand side. + :returns boolean: True if ``a`` has the same bytes as ``b``. + + +.. _`Coda Hale's blog post`: http://codahale.com/a-lesson-in-timing-attacks/ diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index 312d7e69..90ca198a 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -20,7 +20,7 @@ Message Digests .. doctest:: - >>> from cryptography.hazmat.bindings import default_backend + >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import hashes >>> digest = hashes.Hash(hashes.SHA256(), backend=default_backend()) >>> digest.update(b"abc") @@ -39,7 +39,7 @@ Message Digests provider such as those described in :ref:`below <cryptographic-hash-algorithms>`. :param backend: A - :class:`~cryptography.hazmat.bindings.interfaces.HashBackend` + :class:`~cryptography.hazmat.backends.interfaces.HashBackend` provider. .. method:: update(data) diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst index db5e98d3..0c0d0220 100644 --- a/docs/hazmat/primitives/hmac.rst +++ b/docs/hazmat/primitives/hmac.rst @@ -27,7 +27,7 @@ message. .. doctest:: - >>> from cryptography.hazmat.bindings import default_backend + >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import hashes, hmac >>> h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend()) >>> h.update(b"message to hash") @@ -41,7 +41,7 @@ message. provider such as those described in :ref:`Cryptographic Hashes <cryptographic-hash-algorithms>`. :param backend: A - :class:`~cryptography.hazmat.bindings.interfaces.HMACBackend` + :class:`~cryptography.hazmat.backends.interfaces.HMACBackend` provider. .. method:: update(msg) diff --git a/docs/hazmat/primitives/index.rst b/docs/hazmat/primitives/index.rst index 614c414a..b115fdbc 100644 --- a/docs/hazmat/primitives/index.rst +++ b/docs/hazmat/primitives/index.rst @@ -10,4 +10,5 @@ Primitives hmac symmetric-encryption padding + constant-time interfaces diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 4ab91408..f4d0457a 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -12,9 +12,6 @@ Symmetric Encryption key = binascii.unhexlify(b"0" * 32) iv = binascii.unhexlify(b"0" * 32) - from cryptography.hazmat.bindings import default_backend - backend = default_backend() - Symmetric encryption is a way to encrypt (hide the plaintext value) material where the sender and receiver both use the same key. Note that symmetric @@ -37,6 +34,8 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. .. doctest:: >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + >>> from cryptography.hazmat.backends import default_backend + >>> backend = default_backend() >>> cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=backend) >>> encryptor = cipher.encryptor() >>> ct = encryptor.update(b"a secret message") + encryptor.finalize() @@ -52,7 +51,7 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. provider such as those described :ref:`below <symmetric-encryption-modes>`. :param backend: A - :class:`~cryptography.hazmat.bindings.interfaces.CipherBackend` + :class:`~cryptography.hazmat.backends.interfaces.CipherBackend` provider. .. method:: encryptor() @@ -89,7 +88,7 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. Block ciphers require that plaintext or ciphertext always be a multiple of their block size, because of that **padding** is often 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 reccomended + 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.modes.CTR`) you don't have to worry @@ -118,6 +117,36 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. :meth:`update` and :meth:`finalize` will raise :class:`~cryptography.exceptions.AlreadyFinalized`. +.. class:: AEADCipherContext + + When calling ``encryptor()`` or ``decryptor()`` on a ``Cipher`` object + with an AEAD mode you will receive a return object conforming to the + ``AEADCipherContext`` interface (in addition to the ``CipherContext`` + interface). If it is an encryption context it will additionally be an + ``AEADEncryptionContext`` interface. ``AEADCipherContext`` contains an + additional method ``authenticate_additional_data`` for adding additional + authenticated but unencrypted data. You should call this before calls to + ``update``. When you are done call ``finalize()`` to finish the operation. + + .. method:: authenticate_additional_data(data) + + :param bytes data: The data you wish to authenticate but not encrypt. + :raises: :class:`~cryptography.exceptions.AlreadyFinalized` + +.. class:: AEADEncryptionContext + + When creating an encryption context using ``encryptor()`` on a ``Cipher`` + object with an AEAD mode you will receive a return object conforming to the + ``AEADEncryptionContext`` interface (as well as ``AEADCipherContext``). + This interface provides one additional attribute ``tag``. ``tag`` can only + be obtained after ``finalize()``. + + .. attribute:: tag + + :return bytes: Returns the tag value as bytes. + :raises: :class:`~cryptography.exceptions.NotYetFinalized` if called + before the context is finalized. + .. _symmetric-encryption-algorithms: Algorithms @@ -200,8 +229,9 @@ Weak Ciphers .. 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=backend) + >>> cipher = Cipher(algorithm, mode=None, backend=default_backend()) >>> encryptor = cipher.encryptor() >>> ct = encryptor.update(b"a secret message") >>> decryptor = cipher.decryptor() @@ -236,16 +266,18 @@ Modes A good construction looks like: - .. code-block:: pycon + .. 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: - .. code-block:: pycon + .. doctest:: + >>> from cryptography.hazmat.primitives.ciphers.modes import CBC >>> iv = "a" * 16 >>> mode = CBC(iv) @@ -295,6 +327,49 @@ Modes reuse an ``initialization_vector`` with a given ``key``. +.. class:: GCM(initialization_vector, tag=None) + + .. danger:: + + When using this mode you MUST not use the decrypted data until + :meth:`~cryptography.hazmat.primitives.interfaces.CipherContext.finalize` + 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 encrypts the message as well as authenticating it + (and optionally additional data that is not encrypted) simultaneously. + Additional means of verifying integrity (like + :doc:`HMAC </hazmat/primitives/hmac>`) are not necessary. + + :param bytes initialization_vector: Must be random bytes. They do not need + to be kept secret (they can be included + in a transmitted message). NIST + `recommends 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``. + + :param bytes tag: The tag bytes to verify during decryption. When encrypting + this must be None. + + .. doctest:: + + >>> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + >>> from cryptography.hazmat.backends import default_backend + >>> cipher = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend()) + >>> encryptor = cipher.encryptor() + >>> encryptor.authenticate_additional_data(b"authenticated but not encrypted payload") + >>> ct = encryptor.update(b"a secret message") + encryptor.finalize() + >>> tag = encryptor.tag + >>> cipher = Cipher(algorithms.AES(key), modes.GCM(iv, tag), backend) + >>> decryptor = cipher.decryptor() + >>> decryptor.authenticate_additional_data(b"authenticated but not encrypted payload") + >>> decryptor.update(ct) + decryptor.finalize() + 'a secret message' + Insecure Modes -------------- @@ -314,3 +389,4 @@ Insecure Modes .. _`described by Colin Percival`: http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html +.. _`recommends 96-bit IV length`: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf |