Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KMS changes #1723

Merged
merged 10 commits into from
Sep 28, 2018
Merged

KMS changes #1723

merged 10 commits into from
Sep 28, 2018

Conversation

daniel-sanche
Copy link
Member

implements changes suggested in b/113025362 and b/113025156

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Sep 25, 2018
@@ -46,21 +48,22 @@ def decryptRSA(ciphertext, client, key_path):
Decrypt a given ciphertext using an 'RSA_DECRYPT_OAEP_2048_SHA256' private
key stored on Cloud KMS
"""
request_body = {'ciphertext': ciphertext.decode()}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the encrypt snippet0, the corresponding request field is converted to base64 by the snippet. I believe that needs to happen here as well.

kms.projects().locations().keyRings().cryptoKeys().cryptoKeyVersions().asymmetricDecrypt(name='projects/google.com:rra-kms-quickstart/locations/global/keyRings/foo-ring/cryptoKeys/foo-key/cryptoKeyVersions/1', body={'ciphertext': 'foobar'}).execute()
...
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://cloudkms.googleapis.com/v1/projects/google.com:rra-kms-quickstart/locations/global/keyRings/foo-ring/cryptoKeys/foo-key/cryptoKeyVersions/1:asymmetricDecrypt?alt=json returned "Invalid value at 'ciphertext' (TYPE_BYTES),">

I believe the binary data inputs in the body of each request should always be like "base64.b64encode(data).decode('ascii')". This leads to the return type matching the input type (in this case, plaintext comes from base64.b64decode, which returns bytes). I think it'd be best to also document that the input must be "bytes", or the equivalent python 2 type (which I think is str).

ciphertext = base64.b64encode(ciphertext).decode('utf-8')
return ciphertext
ciphertext = public_key.encrypt(plaintext, pad)
return base64.b64encode(ciphertext)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return the bytes returned from public_key.encrypt, without base64 encoding it.

In general, treat base64 as a part of the JSON encoding, because the only reason base64 is used is because JSON only supports UTF-8 strings. base64 is a shim to make non-UTF-8 data compatible with JSON. For that reason, it's clearest to keep the base64 encoding/decoding right before/after the actual HTTP call.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense, I moved the encoding into the decrypt request body

ciphertext_bytes = sample.encryptRSA(self.message_bytes,
self.client,
self.rsaDecrypt)
ciphertext = ciphertext_bytes.decode('utf-8')
# ciphertext should be 344 characters with base64 and RSA 2048
assert len(ciphertext) == 344, \
'ciphertext should be 344 chars; got {}'.format(len(ciphertext))
assert ciphertext[-2:] == '==', 'cipher text should end with =='
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an odd detail to assert, and I'm surprised the test isn't flaky because of it. The API doesn't guarantee anything about the content of the ciphertext. I'd remove this assertion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

self.client,
self.rsaSign)
assert success is True, 'RSA verification failed'
changed_bytes = (self.message+".").encode('utf-8')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: alternatively, changed+bytes = message_bytes + b'.'.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does look nicer. Changed

Copy link

@russ- russ- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

"""
public_key = getAsymmetricPublicKey(client, key_path)

digest_bytes = hashlib.sha256(message.encode('ascii')).digest()
digest_bytes = hashlib.sha256(message).digest()
sig_bytes = base64.b64decode(signature)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signature passed to verifySignature{RSA,EC} should be raw binary. signAsymmetric should b64decode the signature received in the response.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

self.client,
self.rsaDecrypt)
assert plaintext_bytes == self.message_bytes
plaintext = plaintext_bytes.decode('utf-8')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there much value in checking that plaintext == self.message if you've already checked that plaintext_bytes == self.message_bytes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not, but I'd rather err on the side of too many tests, especially when dealing with all these encoding changes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the time you specify utf-8 for string.encode() and bytes.decode(), except on line 51 where you just assume the default (which is utf-8). Both ways work fine, but this is a minor inconsistency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, we should probably keep that consistent. Fixed

Copy link
Contributor

@engelke engelke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@daniel-sanche daniel-sanche merged commit 172ee1d into master Sep 28, 2018
@jmdobry jmdobry deleted the kms-changes branch October 16, 2018 19:11
busunkim96 pushed a commit to googleapis/python-kms that referenced this pull request Jun 4, 2020
rsamborski pushed a commit that referenced this pull request Nov 8, 2022
use byte parameters instead of strings
rsamborski pushed a commit that referenced this pull request Nov 8, 2022
use byte parameters instead of strings
rsamborski pushed a commit that referenced this pull request Nov 11, 2022
use byte parameters instead of strings
rsamborski pushed a commit that referenced this pull request Nov 14, 2022
use byte parameters instead of strings
dandhlee pushed a commit that referenced this pull request Nov 14, 2022
use byte parameters instead of strings
parthea pushed a commit to googleapis/google-cloud-python that referenced this pull request Oct 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants