diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-01-11 21:59:08 -0600 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2014-01-11 21:59:08 -0600 |
commit | 74169660e47b760f82c0653b4210b3bc5d3bf46b (patch) | |
tree | 33835b3e733f6b918b56240200e29402092cc384 /docs/hazmat | |
parent | 9ad4d755bb3a2edfb8e46b60f6dfaff6365f0386 (diff) | |
parent | 089a860f2d3f0ac923fc3f78190055990a940e2a (diff) | |
download | cryptography-74169660e47b760f82c0653b4210b3bc5d3bf46b.tar.gz cryptography-74169660e47b760f82c0653b4210b3bc5d3bf46b.tar.bz2 cryptography-74169660e47b760f82c0653b4210b3bc5d3bf46b.zip |
Merge branch 'master' into urandom-engine
* master: (169 commits)
Make just one call to ffi.cdef for most of the definitions
Use pytest.fixture for backends
drop to >= 0.8 to make pypy happy
change to anonymous enum
require cffi >= 0.8.1
remove extraneous spaces
add hmac to commoncrypto binding
bytes byte back
add check to confirm we've loaded error strings
Bind all the PEM errors
Spelling!
oops, bytes plz
don't leak a context in the test
add tests to the openssl backend to verify that we've registered
Nonsense I think we need.
This is a dep
init the ssl library in the backend
Actuall install a thing
Try to run the spellchecker on travis
Use a normal quote here, not sure where the smart quote came from
...
Conflicts:
cryptography/hazmat/bindings/openssl/binding.py
tests/hazmat/backends/test_openssl.py
Diffstat (limited to 'docs/hazmat')
-rw-r--r-- | docs/hazmat/bindings/commoncrypto.rst | 28 | ||||
-rw-r--r-- | docs/hazmat/bindings/index.rst | 3 | ||||
-rw-r--r-- | docs/hazmat/primitives/hmac.rst | 29 | ||||
-rw-r--r-- | docs/hazmat/primitives/interfaces.rst | 12 | ||||
-rw-r--r-- | docs/hazmat/primitives/symmetric-encryption.rst | 255 |
5 files changed, 222 insertions, 105 deletions
diff --git a/docs/hazmat/bindings/commoncrypto.rst b/docs/hazmat/bindings/commoncrypto.rst new file mode 100644 index 00000000..25535e02 --- /dev/null +++ b/docs/hazmat/bindings/commoncrypto.rst @@ -0,0 +1,28 @@ +.. hazmat:: + +CommonCrypto Binding +==================== + +.. currentmodule:: cryptography.hazmat.bindings.commoncrypto.binding + +These are `CFFI`_ bindings to the `CommonCrypto`_ C library. It is available on +Mac OS X. + +.. class:: cryptography.hazmat.bindings.commoncrypto.binding.Binding() + + This is the exposed API for the CommonCrypto bindings. It has two public + attributes: + + .. attribute:: ffi + + This is a :class:`cffi.FFI` instance. It can be used to allocate and + otherwise manipulate CommonCrypto structures. + + .. attribute:: lib + + This is a ``cffi`` library. It can be used to call CommonCrypto + functions, and access constants. + + +.. _`CFFI`: https://cffi.readthedocs.org/ +.. _`CommonCrypto`: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/Common%20Crypto.3cc.html#//apple_ref/doc/man/3cc/CommonCrypto diff --git a/docs/hazmat/bindings/index.rst b/docs/hazmat/bindings/index.rst index 809eddfc..caab8d6a 100644 --- a/docs/hazmat/bindings/index.rst +++ b/docs/hazmat/bindings/index.rst @@ -6,7 +6,7 @@ Bindings .. currentmodule:: cryptography.hazmat.bindings ``cryptography`` aims to provide low-level CFFI based bindings to multiple -native C libraries. These provide no automatic initialisation of the library +native C libraries. These provide no automatic initialization of the library and may not provide complete wrappers for its API. Using these functions directly is likely to require you to be careful in @@ -20,3 +20,4 @@ Individual Bindings :maxdepth: 1 openssl + commoncrypto diff --git a/docs/hazmat/primitives/hmac.rst b/docs/hazmat/primitives/hmac.rst index b8f94fd2..a21799be 100644 --- a/docs/hazmat/primitives/hmac.rst +++ b/docs/hazmat/primitives/hmac.rst @@ -37,6 +37,16 @@ message. If the backend doesn't support the requested ``algorithm`` an :class:`~cryptography.exceptions.UnsupportedAlgorithm` will be raised. + To check that a given signature is correct use the :meth:`verify` method. + You will receive an exception if the signature is wrong: + + .. code-block:: pycon + + >>> h.verify(b"an incorrect signature") + Traceback (most recent call last): + ... + cryptography.exceptions.InvalidSignature: Signature did not match digest. + :param key: Secret key as ``bytes``. :param algorithm: A :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm` @@ -61,6 +71,17 @@ message. and finalized independently of the original instance. :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` + .. method:: verify(signature) + + Finalize the current context and securely compare digest to + ``signature``. + + :param bytes signature: The bytes to compare the current digest + against. + :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` + :raises cryptography.exceptions.InvalidSignature: If signature does not + match digest + .. method:: finalize() Finalize the current context and return the message digest as bytes. @@ -71,11 +92,3 @@ message. :return bytes: The message digest as bytes. :raises cryptography.exceptions.AlreadyFinalized: - - .. method:: verify(signature) - - Finalize the current context and securely compare digest to ``signature``. - - :param bytes signature: The bytes of the HMAC signature recieved. - :raises cryptography.exceptions.AlreadyFinalized: See :meth:`finalize` - :raises cryptography.exceptions.InvalidSignature: If signature does not match digest diff --git a/docs/hazmat/primitives/interfaces.rst b/docs/hazmat/primitives/interfaces.rst index 361b723e..edb24cd9 100644 --- a/docs/hazmat/primitives/interfaces.rst +++ b/docs/hazmat/primitives/interfaces.rst @@ -67,6 +67,18 @@ Interfaces used by the symmetric cipher modes described in 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 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.modes.CBC` + mode uses this method to check that the provided initialization + vector's length matches the block size of the algorithm. + .. class:: ModeWithInitializationVector diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 30896a05..83165690 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -1,4 +1,4 @@ -.. hazmat:: +.. hazmat:: /fernet Symmetric Encryption @@ -74,79 +74,6 @@ an "encrypt-then-MAC" formulation as `described by Colin Percival`_. and ``mode`` an :class:`cryptography.exceptions.UnsupportedAlgorithm` will be raised. - -.. currentmodule:: cryptography.hazmat.primitives.interfaces - -.. class:: CipherContext - - When calling ``encryptor()`` or ``decryptor()`` on a ``Cipher`` object - you will receive a return object conforming 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 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 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 - about this. - - .. method:: update(data) - - :param bytes data: The data you wish to pass into the context. - :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:: finalize() - - :return bytes: Returns the remainder of the data. - :raises ValueError: This is raised when the data provided isn't - correctly padded to be 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 - :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 @@ -189,15 +116,6 @@ Algorithms ``56`` bits long), they can simply be concatenated to produce the full key. This must be kept secret. -.. class:: CAST5(key) - - CAST5 (also known as CAST-128) is a block cipher approved for use in the - Canadian government by their Communications Security Establishment. It is a - variable key length cipher and supports keys from 40-128 bits in length. - - :param bytes key: The secret key, 40-128 bits in length (in increments of - 8). This must be kept secret. - Weak Ciphers ------------ @@ -251,6 +169,8 @@ Modes 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 bytes initialization_vector: Must be random bytes. They do not need to be kept secret (they can be included in a transmitted message). Must be the @@ -293,6 +213,8 @@ Modes cryptographically strong. It transforms a block cipher into a stream cipher. + **This mode does not require padding.** + :param bytes nonce: Should be random bytes. 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 @@ -306,6 +228,8 @@ Modes 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 bytes initialization_vector: Must be random bytes. They do not need to be kept secret (they can be included in a transmitted message). Must be the @@ -319,6 +243,8 @@ Modes 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 bytes initialization_vector: Must be random bytes. They do not need to be kept secret (they can be included in a transmitted message). Must be the @@ -343,6 +269,8 @@ Modes Additional means of verifying integrity (like :doc:`HMAC </hazmat/primitives/hmac>`) are not necessary. + **This mode does not require padding.** + :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 @@ -365,20 +293,70 @@ Modes :param bytes tag: The tag bytes to verify during decryption. When encrypting this must be None. - .. doctest:: + .. testcode:: - >>> 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' + import os + + 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 a AES-GCM Cipher object with the given and our 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:: + + a secret message! Insecure Modes @@ -397,6 +375,91 @@ Insecure Modes identical plaintext blocks will always result in identical ciphertext blocks, and thus result in information leakage + **Padding is required when using this mode.** + +Interfaces +---------- + +.. class:: CipherContext + + When calling ``encryptor()`` or ``decryptor()`` on a ``Cipher`` object + you will receive a return object conforming 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 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.modes.CTR`) you don't have to worry + about this. + + .. method:: update(data) + + :param bytes data: The data you wish to pass into the context. + :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:: finalize() + + :return bytes: Returns the remainder of the data. + :raises ValueError: This is raised when the data provided isn't + correctly padded to be 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 + :class:`~cryptography.exceptions.AlreadyFinalized`. + +.. class:: AEADCipherContext + + When calling ``encryptor()`` or ``decryptor()`` on a ``Cipher`` object + with an AEAD mode (e.g. + :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM`) you will receive + a return object conforming to the ``AEADCipherContext`` and + ``CipherContext`` interfaces. 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 (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 bytes data: Any 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 (e.g. + :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM`) 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. + .. _`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 |