Skip to content

Commit 909a24b

Browse files
daniel-sanchersamborski
authored andcommitted
KMS changes [(#1723)](#1723)
use byte parameters instead of strings
1 parent 887f48f commit 909a24b

File tree

2 files changed

+43
-38
lines changed

2 files changed

+43
-38
lines changed

kms/snippets/asymmetric.py

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.rom googleapiclient import discovery
1515

16+
# [START kms_asymmetric_imports]
1617
import base64
1718
import hashlib
1819

1920
from cryptography.exceptions import InvalidSignature
2021
from cryptography.hazmat.backends import default_backend
2122
from cryptography.hazmat.primitives import hashes, serialization
2223
from cryptography.hazmat.primitives.asymmetric import ec, padding, utils
24+
# [END kms_asymmetric_imports]
2325

2426

2527
# [START kms_get_asymmetric_public]
@@ -43,35 +45,34 @@ def getAsymmetricPublicKey(client, key_path):
4345
# [START kms_decrypt_rsa]
4446
def decryptRSA(ciphertext, client, key_path):
4547
"""
46-
Decrypt a given ciphertext using an 'RSA_DECRYPT_OAEP_2048_SHA256' private
47-
key stored on Cloud KMS
48+
Decrypt the input ciphertext (bytes) using an
49+
'RSA_DECRYPT_OAEP_2048_SHA256' private key stored on Cloud KMS
4850
"""
51+
request_body = {'ciphertext': base64.b64encode(ciphertext).decode('utf-8')}
4952
request = client.projects() \
5053
.locations() \
5154
.keyRings() \
5255
.cryptoKeys() \
5356
.cryptoKeyVersions() \
5457
.asymmetricDecrypt(name=key_path,
55-
body={'ciphertext': ciphertext})
58+
body=request_body)
5659
response = request.execute()
57-
plaintext = base64.b64decode(response['plaintext']).decode('utf-8')
60+
plaintext = base64.b64decode(response['plaintext'])
5861
return plaintext
5962
# [END kms_decrypt_rsa]
6063

6164

6265
# [START kms_encrypt_rsa]
63-
def encryptRSA(message, client, key_path):
66+
def encryptRSA(plaintext, client, key_path):
6467
"""
65-
Encrypt message locally using an 'RSA_DECRYPT_OAEP_2048_SHA256' public
66-
key retrieved from Cloud KMS
68+
Encrypt the input plaintext (bytes) locally using an
69+
'RSA_DECRYPT_OAEP_2048_SHA256' public key retrieved from Cloud KMS
6770
"""
6871
public_key = getAsymmetricPublicKey(client, key_path)
6972
pad = padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
7073
algorithm=hashes.SHA256(),
7174
label=None)
72-
ciphertext = public_key.encrypt(message.encode('ascii'), pad)
73-
ciphertext = base64.b64encode(ciphertext).decode('utf-8')
74-
return ciphertext
75+
return public_key.encrypt(plaintext, pad)
7576
# [END kms_encrypt_rsa]
7677

7778

@@ -82,7 +83,7 @@ def signAsymmetric(message, client, key_path):
8283
"""
8384
# Note: some key algorithms will require a different hash function
8485
# For example, EC_SIGN_P384_SHA384 requires SHA384
85-
digest_bytes = hashlib.sha256(message.encode('ascii')).digest()
86+
digest_bytes = hashlib.sha256(message).digest()
8687
digest64 = base64.b64encode(digest_bytes)
8788

8889
digest_JSON = {'sha256': digest64.decode('utf-8')}
@@ -94,24 +95,22 @@ def signAsymmetric(message, client, key_path):
9495
.asymmetricSign(name=key_path,
9596
body={'digest': digest_JSON})
9697
response = request.execute()
97-
return response.get('signature', None)
98+
return base64.b64decode(response.get('signature', None))
9899
# [END kms_sign_asymmetric]
99100

100101

101102
# [START kms_verify_signature_rsa]
102103
def verifySignatureRSA(signature, message, client, key_path):
103104
"""
104105
Verify the validity of an 'RSA_SIGN_PSS_2048_SHA256' signature for the
105-
specified plaintext message
106+
specified message
106107
"""
107108
public_key = getAsymmetricPublicKey(client, key_path)
108-
109-
digest_bytes = hashlib.sha256(message.encode('ascii')).digest()
110-
sig_bytes = base64.b64decode(signature)
109+
digest_bytes = hashlib.sha256(message).digest()
111110

112111
try:
113112
# Attempt verification
114-
public_key.verify(sig_bytes,
113+
public_key.verify(signature,
115114
digest_bytes,
116115
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
117116
salt_length=32),
@@ -127,16 +126,14 @@ def verifySignatureRSA(signature, message, client, key_path):
127126
def verifySignatureEC(signature, message, client, key_path):
128127
"""
129128
Verify the validity of an 'EC_SIGN_P256_SHA256' signature
130-
for the specified plaintext message
129+
for the specified message
131130
"""
132131
public_key = getAsymmetricPublicKey(client, key_path)
133-
134-
digest_bytes = hashlib.sha256(message.encode('ascii')).digest()
135-
sig_bytes = base64.b64decode(signature)
132+
digest_bytes = hashlib.sha256(message).digest()
136133

137134
try:
138135
# Attempt verification
139-
public_key.verify(sig_bytes,
136+
public_key.verify(signature,
140137
digest_bytes,
141138
ec.ECDSA(utils.Prehashed(hashes.SHA256())))
142139
# No errors were thrown. Verification was successful

kms/snippets/asymmetric_test.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
1716
from os import environ
1817
from time import sleep
1918

@@ -89,6 +88,7 @@ class TestKMSSamples:
8988
.format(parent, keyring, ecSignId)
9089

9190
message = 'test message 123'
91+
message_bytes = message.encode('utf-8')
9292

9393
client = discovery.build('cloudkms', 'v1')
9494

@@ -99,44 +99,52 @@ def test_get_public_key(self):
9999
assert isinstance(ec_key, _EllipticCurvePublicKey), 'expected EC key'
100100

101101
def test_rsa_encrypt_decrypt(self):
102-
ciphertext = sample.encryptRSA(self.message,
102+
ciphertext = sample.encryptRSA(self.message_bytes,
103103
self.client,
104104
self.rsaDecrypt)
105-
# ciphertext should be 344 characters with base64 and RSA 2048
106-
assert len(ciphertext) == 344, \
107-
'ciphertext should be 344 chars; got {}'.format(len(ciphertext))
108-
assert ciphertext[-2:] == '==', 'cipher text should end with =='
109-
plaintext = sample.decryptRSA(ciphertext, self.client, self.rsaDecrypt)
105+
# ciphertext should be 256 characters with base64 and RSA 2048
106+
assert len(ciphertext) == 256, \
107+
'ciphertext should be 256 chars; got {}'.format(len(ciphertext))
108+
plaintext_bytes = sample.decryptRSA(ciphertext,
109+
self.client,
110+
self.rsaDecrypt)
111+
assert plaintext_bytes == self.message_bytes
112+
plaintext = plaintext_bytes.decode('utf-8')
110113
assert plaintext == self.message
111114

112115
def test_rsa_sign_verify(self):
113-
sig = sample.signAsymmetric(self.message, self.client, self.rsaSign)
116+
sig = sample.signAsymmetric(self.message_bytes,
117+
self.client,
118+
self.rsaSign)
114119
# ciphertext should be 344 characters with base64 and RSA 2048
115-
assert len(sig) == 344, \
116-
'sig should be 344 chars; got {}'.format(len(sig))
117-
assert sig[-2:] == '==', 'sig should end with =='
120+
assert len(sig) == 256, \
121+
'sig should be 256 chars; got {}'.format(len(sig))
118122
success = sample.verifySignatureRSA(sig,
119-
self.message,
123+
self.message_bytes,
120124
self.client,
121125
self.rsaSign)
122126
assert success is True, 'RSA verification failed'
127+
changed_bytes = self.message_bytes + b'.'
123128
success = sample.verifySignatureRSA(sig,
124-
self.message+'.',
129+
changed_bytes,
125130
self.client,
126131
self.rsaSign)
127132
assert success is False, 'verify should fail with modified message'
128133

129134
def test_ec_sign_verify(self):
130-
sig = sample.signAsymmetric(self.message, self.client, self.ecSign)
135+
sig = sample.signAsymmetric(self.message_bytes,
136+
self.client,
137+
self.ecSign)
131138
assert len(sig) > 50 and len(sig) < 300, \
132139
'sig outside expected length range'
133140
success = sample.verifySignatureEC(sig,
134-
self.message,
141+
self.message_bytes,
135142
self.client,
136143
self.ecSign)
137144
assert success is True, 'EC verification failed'
145+
changed_bytes = self.message_bytes + b'.'
138146
success = sample.verifySignatureEC(sig,
139-
self.message+'.',
147+
changed_bytes,
140148
self.client,
141149
self.ecSign)
142150
assert success is False, 'verify should fail with modified message'

0 commit comments

Comments
 (0)