diff --git a/kms/snippets/decrypt_asymmetric.py b/kms/snippets/decrypt_asymmetric.py index 7f5397c92392..006d5afb9637 100644 --- a/kms/snippets/decrypt_asymmetric.py +++ b/kms/snippets/decrypt_asymmetric.py @@ -39,8 +39,37 @@ def decrypt_asymmetric(project_id, location_id, key_ring_id, key_id, version_id, # Build the key version name. key_version_name = client.crypto_key_version_path(project_id, location_id, key_ring_id, key_id, version_id) + # Optional, but recommended: compute ciphertext's CRC32C. + # See crc32c() function defined below. + ciphertext_crc32c = crc32c(ciphertext) + # Call the API. - decrypt_response = client.asymmetric_decrypt(request={'name': key_version_name, 'ciphertext': ciphertext}) + decrypt_response = client.asymmetric_decrypt( + request={'name': key_version_name, 'ciphertext': ciphertext, 'ciphertext_crc32c': ciphertext_crc32c}) + + # Optional, but recommended: perform integrity verification on decrypt_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 decrypt_response.verified_ciphertext_crc32c: + raise Exception('The request sent to the server was corrupted in-transit.') + if not decrypt_response.plaintext_crc32c == crc32c(decrypt_response.plaintext): + raise Exception('The response received from the server was corrupted in-transit.') + # End integrity verification + print('Plaintext: {}'.format(decrypt_response.plaintext)) return decrypt_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_decrypt_asymmetric] diff --git a/kms/snippets/decrypt_symmetric.py b/kms/snippets/decrypt_symmetric.py index c0b64d3b2d16..8c6ec724f2c3 100644 --- a/kms/snippets/decrypt_symmetric.py +++ b/kms/snippets/decrypt_symmetric.py @@ -38,8 +38,35 @@ def decrypt_symmetric(project_id, location_id, key_ring_id, key_id, ciphertext): # Build the key name. key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id) + # Optional, but recommended: compute ciphertext's CRC32C. + # See crc32c() function defined below. + ciphertext_crc32c = crc32c(ciphertext) + # Call the API. - decrypt_response = client.decrypt(request={'name': key_name, 'ciphertext': ciphertext}) + decrypt_response = client.decrypt( + request={'name': key_name, 'ciphertext': ciphertext, 'ciphertext_crc32c': ciphertext_crc32c}) + + # Optional, but recommended: perform integrity verification on decrypt_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 decrypt_response.plaintext_crc32c == crc32c(decrypt_response.plaintext): + raise Exception('The response received from the server was corrupted in-transit.') + # End integrity verification + print('Plaintext: {}'.format(decrypt_response.plaintext)) return decrypt_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_decrypt_symmetric] diff --git a/kms/snippets/get_public_key.py b/kms/snippets/get_public_key.py index bdc91139944d..e265f7fd67b3 100644 --- a/kms/snippets/get_public_key.py +++ b/kms/snippets/get_public_key.py @@ -40,6 +40,31 @@ def get_public_key(project_id, location_id, key_ring_id, key_id, version_id): # Call the API. public_key = client.get_public_key(request={'name': key_version_name}) + + # Optional, but recommended: perform integrity verification on public_key. + # 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 public_key.name == key_version_name: + raise Exception('The request sent to the server was corrupted in-transit.') + # See crc32c() function defined below. + if not public_key.pem_crc32c == crc32c(public_key.pem): + raise Exception('The response received from the server was corrupted in-transit.') + # End integrity verification + print('Public key: {}'.format(public_key.pem)) return public_key + + +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_get_public_key] diff --git a/kms/snippets/sign_asymmetric.py b/kms/snippets/sign_asymmetric.py index c12a31d2d1f5..6b8baa7a7747 100644 --- a/kms/snippets/sign_asymmetric.py +++ b/kms/snippets/sign_asymmetric.py @@ -27,7 +27,6 @@ def sign_asymmetric(project_id, location_id, key_ring_id, key_id, version_id, me Returns: AsymmetricSignResponse: Signature. - """ # Import the client library. @@ -57,8 +56,39 @@ def sign_asymmetric(project_id, location_id, key_ring_id, key_id, version_id, me # example, EC_SIGN_P384_SHA384 requires SHA-384. digest = {'sha256': hash_} + # Optional, but recommended: compute digest's CRC32C. + # See crc32c() function defined below. + digest_crc32c = crc32c(hash_) + # Call the API - sign_response = client.asymmetric_sign(request={'name': key_version_name, 'digest': digest}) + sign_response = client.asymmetric_sign( + request={'name': key_version_name, 'digest': digest, 'digest_crc32c': digest_crc32c}) + + # Optional, but recommended: perform integrity verification on sign_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 sign_response.verified_digest_crc32c: + raise Exception('The request sent to the server was corrupted in-transit.') + if not sign_response.name == key_version_name: + raise Exception('The request sent to the server was corrupted in-transit.') + if not sign_response.signature_crc32c == crc32c(sign_response.signature): + raise Exception('The response received from the server was corrupted in-transit.') + # End integrity verification + print('Signature: {}'.format(base64.b64encode(sign_response.signature))) return sign_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_sign_asymmetric]