From 78569d68de24bc56dd799c262f3dd2d522bcdcd1 Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 7 Jan 2014 15:42:17 -0800 Subject: Try making the AEAD examples less dense. --- docs/hazmat/primitives/symmetric-encryption.rst | 51 ++++++++++++++++++------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'docs') diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index e05248ff..d3ba731a 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -365,20 +365,45 @@ Modes :param bytes tag: The tag bytes to verify during decryption. When encrypting this must be None. - .. doctest:: + .. code-block:: python - >>> 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' + def encrypt(key, plaintext, associated_data): + iv = os.urandom(12) + cipher = Cipher( + algorithms.AES(key), + modes.GCM(iv), + backend=default_backend() + ) + + encryptor = cipher.encryptor() + encryptor.authenticate_additional_data(associated_data) + ciphertext = encryptor.update(plaintext) + encryptor.finalize() + + return (associated_data, iv, ciphertext, encryptor.tag) + + def decrypt(key, associated_data, iv, ciphertext, tag): + cipher = Cipher( + algorithms.AES(key), + modes.GCM(iv, tag), + backend=default_backend() + ) + + decryptor = cipher.decryptor() + decryptor.authenticate_additional_data(associated_data) + + return decryptor.update(ciphertext) + decryptor.finalize() + + associated_data, iv, ciphertext, tag = encrypt( + key, + b"a secret message", + b"authenticated but not encrypted payload" + ) + + print(decrypt(key, associated_data, iv, ciphertext, tag)) + + .. testoutput:: + + a secret message Insecure Modes -- cgit v1.2.3 From abb72d23118fb63a8601d2036b7c2cef2598f408 Mon Sep 17 00:00:00 2001 From: David Reid Date: Tue, 7 Jan 2014 16:06:18 -0800 Subject: Make the example more complete and add some comments walking the user through some stuff. --- docs/hazmat/primitives/symmetric-encryption.rst | 63 +++++++++++++++++++------ 1 file changed, 49 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index d3ba731a..59aff99b 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -365,45 +365,80 @@ Modes :param bytes tag: The tag bytes to verify during decryption. When encrypting this must be None. - .. code-block:: python + .. testcode:: + + import os + + from cryptography.hazmat.primitives.ciphers import ( + Cipher, algorithms, modes + ) + + from cryptography.hazmat.primitives.padding import PKCS7 def encrypt(key, plaintext, associated_data): + # Generate a random 96-bit IV. iv = os.urandom(12) - cipher = Cipher( + + # 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() - encryptor = cipher.encryptor() + # We have to pad our plaintext because it may not be a + # multiple of the block size. + padder = PKCS7(algorithms.AES.block_size).padder() + padded_plaintext = padder.update(plaintext) + padder.finalize() + + # associated_data will be authenticated but not encrypted, + # it must also be passed in on decryption. encryptor.authenticate_additional_data(associated_data) - ciphertext = encryptor.update(plaintext) + encryptor.finalize() - return (associated_data, iv, ciphertext, encryptor.tag) + # Encrypt the plaintext and get the associated ciphertext. + ciphertext = encryptor.update(padded_plaintext) + encryptor.finalize() + + return (iv, ciphertext, encryptor.tag) def decrypt(key, associated_data, iv, ciphertext, tag): - cipher = Cipher( + # 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 will need to unpad the plaintext. + unpadder = PKCS7(algorithms.AES.block_size).unpadder() - decryptor = cipher.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) - return decryptor.update(ciphertext) + decryptor.finalize() + # Decryption gets us the authenticated padded plaintext. + padded_plaintext = decryptor.update(ciphertext) + decryptor.finalize() - associated_data, iv, ciphertext, tag = encrypt( + return unpadder.update(padded_plaintext) + unpadder.finalize() + + iv, ciphertext, tag = encrypt( key, - b"a secret message", + b"a secret message!", b"authenticated but not encrypted payload" ) - print(decrypt(key, associated_data, iv, ciphertext, tag)) + print(decrypt( + key, + b"authenticated but not encrypted payload", + iv, + ciphertext, + tag + )) .. testoutput:: - a secret message + a secret message! Insecure Modes -- cgit v1.2.3