Skip to content

Commit

Permalink
samples: Add request/response integrity verification to crypto operat…
Browse files Browse the repository at this point in the history
…ions (#72)
  • Loading branch information
iamtamjam authored and dandhlee committed Nov 14, 2022
1 parent 2be9a7d commit 02b7f92
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 4 deletions.
31 changes: 30 additions & 1 deletion kms/snippets/decrypt_asymmetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
29 changes: 28 additions & 1 deletion kms/snippets/decrypt_symmetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
25 changes: 25 additions & 0 deletions kms/snippets/get_public_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
34 changes: 32 additions & 2 deletions kms/snippets/sign_asymmetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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]

0 comments on commit 02b7f92

Please sign in to comment.