aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/architecture.rst6
-rw-r--r--docs/conf.py1
-rw-r--r--docs/contributing.rst44
-rw-r--r--docs/exceptions.rst12
-rw-r--r--docs/glossary.rst11
-rw-r--r--docs/hazmat/backends/index.rst (renamed from docs/hazmat/bindings/index.rst)2
-rw-r--r--docs/hazmat/backends/interfaces.rst (renamed from docs/hazmat/bindings/interfaces.rst)6
-rw-r--r--docs/hazmat/backends/openssl.rst (renamed from docs/hazmat/bindings/openssl.rst)4
-rw-r--r--docs/hazmat/primitives/constant-time.rst38
-rw-r--r--docs/hazmat/primitives/cryptographic-hashes.rst4
-rw-r--r--docs/hazmat/primitives/hmac.rst4
-rw-r--r--docs/hazmat/primitives/index.rst1
-rw-r--r--docs/hazmat/primitives/symmetric-encryption.rst92
-rw-r--r--docs/index.rst23
14 files changed, 218 insertions, 30 deletions
diff --git a/docs/architecture.rst b/docs/architecture.rst
index 5ca2c252..bacde1bb 100644
--- a/docs/architecture.rst
+++ b/docs/architecture.rst
@@ -8,6 +8,6 @@ Architecture
``cryptography.hazmat.primitives``.
* ``cryptography.hazmat.primitives``: This packages contains low level
algorithms, things like ``AES`` or ``SHA1``. This is implemented on top of
- ``cryptography.hazmat.bindings``.
-* ``cryptography.hazmat.bindings``: This package contains bindings to low level
- cryptographic libraries. Our initial target will be OpenSSL.
+ ``cryptography.hazmat.backends``.
+* ``cryptography.hazmat.backends``: This package contains bindings to low level
+ cryptographic libraries. Our initial target is OpenSSL.
diff --git a/docs/conf.py b/docs/conf.py
index 77050e72..5092e4d3 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -257,6 +257,5 @@ texinfo_documents = [
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
-
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
diff --git a/docs/contributing.rst b/docs/contributing.rst
index 97f31e0b..cb9c7283 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -28,6 +28,7 @@ devastating, ``cryptography`` has a strict code review policy:
* If somehow the tests get into a failing state on ``master`` (such as by a
backwards incompatible release of a dependency) no pull requests may be
merged until this is rectified.
+* All merged patches must have 100% test coverage.
The purpose of these policies is to minimize the chances we merge a change
which jeopardizes our users' security.
@@ -47,8 +48,42 @@ Additionally, every Python code file must contain
from __future__ import absolute_import, division, print_function
+API Considerations
+~~~~~~~~~~~~~~~~~~
+
+Most projects' APIs are designed with a philosophy of "make easy things easy,
+and make hard things possible". One of the perils of writing cryptographic code
+is that code that is secure looks just like code that isn't, and produces
+results that are also difficult to distinguish. As a result ``cryptography``
+has, as a design philosophy: "make it hard to do insecure things". Here are a
+few strategies for API design which should be both followed, and should inspire
+other API choices:
+
+If it is incorrect to ignore the result of a method, it should raise an
+exception, and not return a boolean ``True``/``False`` flag. For example, a
+method to verify a signature should raise ``InvalidSignature``, and not return
+whether the signature was valid.
+
+.. code-block:: python
+
+ # This is bad.
+ def verify(sig):
+ # ...
+ return is_valid
+
+ # Good!
+ def verify(sig):
+ # ...
+ if not is_valid:
+ raise InvalidSignature
+
+APIs at the :doc:`/hazmat/primitives/index` layer should always take an
+explicit backend, APIs at the recipes layer should automatically use the
+:func:`~cryptography.hazmat.backends.default_backend`, but optionally allow
+specifying a different backend.
+
C bindings
-----------
+~~~~~~~~~~
When binding C code with ``cffi`` we have our own style guide, it's pretty
simple.
@@ -141,6 +176,9 @@ should begin with the "Hazardous Materials" warning:
.. hazmat::
+When referring to a hypothetical individual (such as "a person receiving an
+encrypted message") use gender neutral pronouns (they/them/their).
+
Development Environment
-----------------------
@@ -158,7 +196,7 @@ dependencies, install ``cryptography`` in ``editable`` mode. For example:
You are now ready to run the tests and build the documentation.
Running Tests
--------------
+~~~~~~~~~~~~~
``cryptography`` unit tests are found in the ``tests/`` directory and are
designed to be run using `pytest`_. `pytest`_ will discover the tests
@@ -192,7 +230,7 @@ You may not have all the required Python versions installed, in which case you
will see one or more ``InterpreterNotFound`` errors.
Building Documentation
-----------------------
+~~~~~~~~~~~~~~~~~~~~~~
``cryptography`` documentation is stored in the ``docs/`` directory. It is
written in `reStructured Text`_ and rendered using `Sphinx`_.
diff --git a/docs/exceptions.rst b/docs/exceptions.rst
index c6f5a7cc..087066b8 100644
--- a/docs/exceptions.rst
+++ b/docs/exceptions.rst
@@ -8,6 +8,18 @@ Exceptions
This is raised when a context is used after being finalized.
+.. class:: NotYetFinalized
+
+ This is raised when the AEAD tag property is accessed on a context
+ before it is finalized.
+
+
+.. class:: AlreadyUpdated
+
+ This is raised when additional data is added to a context after update
+ has already been called.
+
+
.. class:: UnsupportedAlgorithm
This is raised when a backend doesn't support the requested algorithm (or
diff --git a/docs/glossary.rst b/docs/glossary.rst
index b6f2d06f..63e0a6ce 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -28,3 +28,14 @@ Glossary
asymmetric cryptography
Cryptographic operations where encryption and decryption use different
keys. There are separate encryption and decryption keys.
+
+ authentication
+ The process of verifying that a message was created by a specific
+ individual (or program). Like encryption, authentication can be either
+ symmetric or asymmetric. Authentication is necessary for effective
+ encryption.
+
+ Ciphertext indistinguishability
+ This is a property of encryption systems whereby two encrypted messages
+ aren't distinguishable without knowing the encryption key. This is
+ considered a basic, necessary property for a working encryption system.
diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/backends/index.rst
index 746f4596..a89cf0d5 100644
--- a/docs/hazmat/bindings/index.rst
+++ b/docs/hazmat/backends/index.rst
@@ -13,7 +13,7 @@ Bindings
Getting a Backend Provider
~~~~~~~~~~~~~~~~~~~~~~~~~~
-.. currentmodule:: cryptography.hazmat.bindings
+.. currentmodule:: cryptography.hazmat.backends
``cryptography`` aims to support multiple backends to ensure it can provide
the widest number of supported cryptographic algorithms as well as supporting
diff --git a/docs/hazmat/bindings/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index c55d86dc..b524943d 100644
--- a/docs/hazmat/bindings/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -3,7 +3,7 @@
Backend Interfaces
==================
-.. currentmodule:: cryptography.hazmat.bindings.interfaces
+.. currentmodule:: cryptography.hazmat.backends.interfaces
Backend implementations may provide a number of interfaces to support operations
@@ -69,6 +69,8 @@ A specific ``backend`` may provide one or more of these interfaces.
:returns:
:class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+ :raises ValueError: When tag is not None in an AEAD mode
+
.. method:: create_symmetric_decryption_ctx(cipher, mode)
@@ -86,6 +88,8 @@ A specific ``backend`` may provide one or more of these interfaces.
:returns:
:class:`~cryptography.hazmat.primitives.interfaces.CipherContext`
+ :raises ValueError: When tag is None in an AEAD mode
+
.. class:: HashBackend
diff --git a/docs/hazmat/bindings/openssl.rst b/docs/hazmat/backends/openssl.rst
index 194eeb92..12fbff04 100644
--- a/docs/hazmat/bindings/openssl.rst
+++ b/docs/hazmat/backends/openssl.rst
@@ -5,7 +5,7 @@ OpenSSL
These are `CFFI`_ bindings to the `OpenSSL`_ C library.
-.. data:: cryptography.hazmat.bindings.openssl.backend
+.. data:: cryptography.hazmat.backends.openssl.backend
This is the exposed API for the OpenSSL bindings. It has two public
attributes:
@@ -21,5 +21,5 @@ These are `CFFI`_ bindings to the `OpenSSL`_ C library.
and access constants.
-.. _`CFFI`: http://cffi.readthedocs.org/
+.. _`CFFI`: https://cffi.readthedocs.org/
.. _`OpenSSL`: https://www.openssl.org/
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
diff --git a/docs/index.rst b/docs/index.rst
index 1b88e24e..776c9d37 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,18 +1,27 @@
Welcome to ``cryptography``
===========================
-.. warning::
+``cryptography`` is a Python library which exposes cryptographic recipes and
+primitives. We hope it'll be your one-stop-shop for all your cryptographic
+needs in Python.
- ``cryptography`` is very young, and very incomplete.
+Installing
+----------
-``cryptography`` is a Python library which exposes cryptographic recipes and
-primitives.
+We don't yet have a release on PyPI, for now you can install ``cryptography``
+directly from Github:
+
+.. code-block:: console
+
+ $ pip install git+https://github.com/pyca/cryptography
Why a new crypto library for Python?
------------------------------------
-We wanted to address a few issues with existing cryptography libraries in
-Python:
+If you've done cryptographic work in Python before, you've probably seen some
+other libraries in Python, such as *M2Crypto*, *PyCrypto*, or *PyOpenSSL*. In
+building ``cryptography`` we wanted to address a few issues we observed in the
+existing libraries:
* Lack of PyPy and Python 3 support.
* Lack of maintenance.
@@ -44,4 +53,4 @@ Hazardous Materials
:maxdepth: 2
hazmat/primitives/index
- hazmat/bindings/index
+ hazmat/backends/index