From abe0570c76f2534495e985f94df8ec34ef9f61ad Mon Sep 17 00:00:00 2001 From: Tamara Aviv <73185172+iamtamjam@users.noreply.github.com> Date: Thu, 12 Nov 2020 14:06:39 -0500 Subject: [PATCH] samples: add request/response integrity verification to encrypt_symmetric.py (#70) --- kms/snippets/encrypt_symmetric.py | 33 ++++++++++++++++++++++++++++++- kms/snippets/requirements.txt | 3 ++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/kms/snippets/encrypt_symmetric.py b/kms/snippets/encrypt_symmetric.py index 9cc3b1a5d12c..9340133b8b3d 100644 --- a/kms/snippets/encrypt_symmetric.py +++ b/kms/snippets/encrypt_symmetric.py @@ -38,6 +38,10 @@ def encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext): # Convert the plaintext to bytes. plaintext_bytes = plaintext.encode('utf-8') + # Optional, but recommended: compute plaintext's CRC32C. + # See crc32c() function defined below. + plaintext_crc32c = crc32c(plaintext_bytes) + # Create the client. client = kms.KeyManagementServiceClient() @@ -45,7 +49,34 @@ def encrypt_symmetric(project_id, location_id, key_ring_id, key_id, plaintext): key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id) # Call the API. - encrypt_response = client.encrypt(request={'name': key_name, 'plaintext': plaintext_bytes}) + encrypt_response = client.encrypt( + request={'name': key_name, 'plaintext': plaintext_bytes, 'plaintext_crc32c': plaintext_crc32c}) + + # Optional, but recommended: perform integrity verification on encrypt_response. + # For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit: + # https://cloud.google.com/kms/docs/data-integrity-guidelines + if not encrypt_response.verified_plaintext_crc32c: + raise Exception('The request sent to the server was corrupted in-transit.') + if not encrypt_response.ciphertext_crc32c == crc32c(encrypt_response.ciphertext): + raise Exception('The response received from the server was corrupted in-transit.') + # End integrity verification + print('Ciphertext: {}'.format(base64.b64encode(encrypt_response.ciphertext))) return encrypt_response + + +def crc32c(data): + """ + Calculates the CRC32C checksum of the provided data. + + Args: + data: the bytes over which the checksum should be calculated. + + Returns: + An int representing the CRC32C checksum of the provided bytes. + """ + import crcmod + import six + crc32c_fun = crcmod.predefined.mkPredefinedCrcFun('crc-32c') + return crc32c_fun(six.ensure_binary(data)) # [END kms_encrypt_symmetric] diff --git a/kms/snippets/requirements.txt b/kms/snippets/requirements.txt index 4ad464f21f06..8cb81ca5c7c1 100644 --- a/kms/snippets/requirements.txt +++ b/kms/snippets/requirements.txt @@ -1,2 +1,3 @@ google-cloud-kms==2.2.0 -cryptography==3.2.1 \ No newline at end of file +cryptography==3.2.1 +crcmod==1.7