Skip to content

Commit 326aef2

Browse files
iamtamjamrsamborski
authored andcommitted
samples: Add request/response integrity verification to crypto operations (#72)
1 parent 91488e2 commit 326aef2

File tree

4 files changed

+115
-4
lines changed

4 files changed

+115
-4
lines changed

kms/snippets/decrypt_asymmetric.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,37 @@ def decrypt_asymmetric(project_id, location_id, key_ring_id, key_id, version_id,
3939
# Build the key version name.
4040
key_version_name = client.crypto_key_version_path(project_id, location_id, key_ring_id, key_id, version_id)
4141

42+
# Optional, but recommended: compute ciphertext's CRC32C.
43+
# See crc32c() function defined below.
44+
ciphertext_crc32c = crc32c(ciphertext)
45+
4246
# Call the API.
43-
decrypt_response = client.asymmetric_decrypt(request={'name': key_version_name, 'ciphertext': ciphertext})
47+
decrypt_response = client.asymmetric_decrypt(
48+
request={'name': key_version_name, 'ciphertext': ciphertext, 'ciphertext_crc32c': ciphertext_crc32c})
49+
50+
# Optional, but recommended: perform integrity verification on decrypt_response.
51+
# For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
52+
# https://cloud.google.com/kms/docs/data-integrity-guidelines
53+
if not decrypt_response.verified_ciphertext_crc32c:
54+
raise Exception('The request sent to the server was corrupted in-transit.')
55+
if not decrypt_response.plaintext_crc32c == crc32c(decrypt_response.plaintext):
56+
raise Exception('The response received from the server was corrupted in-transit.')
57+
# End integrity verification
58+
4459
print('Plaintext: {}'.format(decrypt_response.plaintext))
4560
return decrypt_response
61+
62+
63+
def crc32c(data):
64+
"""
65+
Calculates the CRC32C checksum of the provided data.
66+
Args:
67+
data: the bytes over which the checksum should be calculated.
68+
Returns:
69+
An int representing the CRC32C checksum of the provided bytes.
70+
"""
71+
import crcmod
72+
import six
73+
crc32c_fun = crcmod.predefined.mkPredefinedCrcFun('crc-32c')
74+
return crc32c_fun(six.ensure_binary(data))
4675
# [END kms_decrypt_asymmetric]

kms/snippets/decrypt_symmetric.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,35 @@ def decrypt_symmetric(project_id, location_id, key_ring_id, key_id, ciphertext):
3838
# Build the key name.
3939
key_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id)
4040

41+
# Optional, but recommended: compute ciphertext's CRC32C.
42+
# See crc32c() function defined below.
43+
ciphertext_crc32c = crc32c(ciphertext)
44+
4145
# Call the API.
42-
decrypt_response = client.decrypt(request={'name': key_name, 'ciphertext': ciphertext})
46+
decrypt_response = client.decrypt(
47+
request={'name': key_name, 'ciphertext': ciphertext, 'ciphertext_crc32c': ciphertext_crc32c})
48+
49+
# Optional, but recommended: perform integrity verification on decrypt_response.
50+
# For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
51+
# https://cloud.google.com/kms/docs/data-integrity-guidelines
52+
if not decrypt_response.plaintext_crc32c == crc32c(decrypt_response.plaintext):
53+
raise Exception('The response received from the server was corrupted in-transit.')
54+
# End integrity verification
55+
4356
print('Plaintext: {}'.format(decrypt_response.plaintext))
4457
return decrypt_response
58+
59+
60+
def crc32c(data):
61+
"""
62+
Calculates the CRC32C checksum of the provided data.
63+
Args:
64+
data: the bytes over which the checksum should be calculated.
65+
Returns:
66+
An int representing the CRC32C checksum of the provided bytes.
67+
"""
68+
import crcmod
69+
import six
70+
crc32c_fun = crcmod.predefined.mkPredefinedCrcFun('crc-32c')
71+
return crc32c_fun(six.ensure_binary(data))
4572
# [END kms_decrypt_symmetric]

kms/snippets/get_public_key.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,31 @@ def get_public_key(project_id, location_id, key_ring_id, key_id, version_id):
4040

4141
# Call the API.
4242
public_key = client.get_public_key(request={'name': key_version_name})
43+
44+
# Optional, but recommended: perform integrity verification on public_key.
45+
# For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
46+
# https://cloud.google.com/kms/docs/data-integrity-guidelines
47+
if not public_key.name == key_version_name:
48+
raise Exception('The request sent to the server was corrupted in-transit.')
49+
# See crc32c() function defined below.
50+
if not public_key.pem_crc32c == crc32c(public_key.pem):
51+
raise Exception('The response received from the server was corrupted in-transit.')
52+
# End integrity verification
53+
4354
print('Public key: {}'.format(public_key.pem))
4455
return public_key
56+
57+
58+
def crc32c(data):
59+
"""
60+
Calculates the CRC32C checksum of the provided data.
61+
Args:
62+
data: the bytes over which the checksum should be calculated.
63+
Returns:
64+
An int representing the CRC32C checksum of the provided bytes.
65+
"""
66+
import crcmod
67+
import six
68+
crc32c_fun = crcmod.predefined.mkPredefinedCrcFun('crc-32c')
69+
return crc32c_fun(six.ensure_binary(data))
4570
# [END kms_get_public_key]

kms/snippets/sign_asymmetric.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ def sign_asymmetric(project_id, location_id, key_ring_id, key_id, version_id, me
2727
2828
Returns:
2929
AsymmetricSignResponse: Signature.
30-
3130
"""
3231

3332
# Import the client library.
@@ -57,8 +56,39 @@ def sign_asymmetric(project_id, location_id, key_ring_id, key_id, version_id, me
5756
# example, EC_SIGN_P384_SHA384 requires SHA-384.
5857
digest = {'sha256': hash_}
5958

59+
# Optional, but recommended: compute digest's CRC32C.
60+
# See crc32c() function defined below.
61+
digest_crc32c = crc32c(hash_)
62+
6063
# Call the API
61-
sign_response = client.asymmetric_sign(request={'name': key_version_name, 'digest': digest})
64+
sign_response = client.asymmetric_sign(
65+
request={'name': key_version_name, 'digest': digest, 'digest_crc32c': digest_crc32c})
66+
67+
# Optional, but recommended: perform integrity verification on sign_response.
68+
# For more details on ensuring E2E in-transit integrity to and from Cloud KMS visit:
69+
# https://cloud.google.com/kms/docs/data-integrity-guidelines
70+
if not sign_response.verified_digest_crc32c:
71+
raise Exception('The request sent to the server was corrupted in-transit.')
72+
if not sign_response.name == key_version_name:
73+
raise Exception('The request sent to the server was corrupted in-transit.')
74+
if not sign_response.signature_crc32c == crc32c(sign_response.signature):
75+
raise Exception('The response received from the server was corrupted in-transit.')
76+
# End integrity verification
77+
6278
print('Signature: {}'.format(base64.b64encode(sign_response.signature)))
6379
return sign_response
80+
81+
82+
def crc32c(data):
83+
"""
84+
Calculates the CRC32C checksum of the provided data.
85+
Args:
86+
data: the bytes over which the checksum should be calculated.
87+
Returns:
88+
An int representing the CRC32C checksum of the provided bytes.
89+
"""
90+
import crcmod
91+
import six
92+
crc32c_fun = crcmod.predefined.mkPredefinedCrcFun('crc-32c')
93+
return crc32c_fun(six.ensure_binary(data))
6494
# [END kms_sign_asymmetric]

0 commit comments

Comments
 (0)