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: Updated for new client library #1903

Merged
merged 5 commits into from
Jan 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions kms/api-client/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,5 @@ To run this sample:

$ python snippets.py

usage: snippets.py [-h]
{create_key_ring,create_crypto_key,encrypt,decrypt,disable_crypto_key_version,enable_crypto_key_version,destroy_crypto_key_version,restore_crypto_key_version,add_member_to_crypto_key_policy,get_key_ring_policy}
...

positional arguments:
{create_key_ring,create_crypto_key,encrypt,decrypt,disable_crypto_key_version,enable_crypto_key_version,destroy_crypto_key_version,restore_crypto_key_version,add_member_to_crypto_key_policy,get_key_ring_policy}

optional arguments:
-h, --help show this help message and exit





.. _Google Cloud SDK: https://cloud.google.com/sdk/
.. _Google Cloud SDK: https://cloud.google.com/sdk/
4 changes: 3 additions & 1 deletion kms/api-client/README.rst.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ samples:
- name: Snippets
file: snippets.py
show_help: True
- name: Asymmetric
file: asymmetric.py

folder: kms/api-client
folder: kms/api-client
137 changes: 93 additions & 44 deletions kms/api-client/asymmetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,71 +13,103 @@
# See the License for the specific language governing permissions and
# limitations under the License.rom googleapiclient import discovery

import base64
import hashlib

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec, padding, utils

from google.cloud import kms_v1
from google.cloud.kms_v1 import enums


# [START kms_create_asymmetric_key]
def create_asymmetric_key(project_id, location_id, key_ring_id, crypto_key_id):
"""Creates an RSA encrypt/decrypt key pair within a specified KeyRing."""

# Creates an API client for the KMS API.
client = kms_v1.KeyManagementServiceClient()

# The resource name of the KeyRing associated with the CryptoKey.
parent = client.key_ring_path(project_id, location_id, key_ring_id)

# Create the CryptoKey object template
purpose = enums.CryptoKey.CryptoKeyPurpose.ASYMMETRIC_DECRYPT
algorithm = enums.CryptoKeyVersion.CryptoKeyVersionAlgorithm.\
RSA_DECRYPT_OAEP_2048_SHA256
crypto_key = {'purpose': purpose,
'version_template': {'algorithm': algorithm}}

# Create a CryptoKey for the given KeyRing.
response = client.create_crypto_key(parent, crypto_key_id, crypto_key)

print('Created CryptoKey {}.'.format(response.name))
return response
# [END kms_create_asymmetric_key]


# [START kms_get_asymmetric_public]
def getAsymmetricPublicKey(client, key_path):
def get_asymmetric_public_key(key_name):
"""
Retrieves the public key from a saved asymmetric key pair on Cloud KMS

Example key_name:
"projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
/KEY_ID/cryptoKeyVersions/1"

Requires:
cryptography.hazmat.backends.default_backend
cryptography.hazmat.primitives.serialization
"""
request = client.projects() \
.locations() \
.keyRings() \
.cryptoKeys() \
.cryptoKeyVersions() \
.getPublicKey(name=key_path)
response = request.execute()
key_txt = response['pem'].encode('ascii')

client = kms_v1.KeyManagementServiceClient()
response = client.get_public_key(key_name)
daniel-sanche marked this conversation as resolved.
Show resolved Hide resolved

key_txt = response.pem.encode('ascii')
key = serialization.load_pem_public_key(key_txt, default_backend())
return key
# [END kms_get_asymmetric_public]


# [START kms_decrypt_rsa]
def decryptRSA(ciphertext, client, key_path):
def decrypt_rsa(ciphertext, key_name):
"""
Decrypt the input ciphertext (bytes) using an
'RSA_DECRYPT_OAEP_2048_SHA256' private key stored on Cloud KMS

Requires:
base64
Example key_name:
"projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
/KEY_ID/cryptoKeyVersions/1"
"""
request_body = {'ciphertext': base64.b64encode(ciphertext).decode('utf-8')}
request = client.projects() \
.locations() \
.keyRings() \
.cryptoKeys() \
.cryptoKeyVersions() \
.asymmetricDecrypt(name=key_path,
body=request_body)
response = request.execute()
plaintext = base64.b64decode(response['plaintext'])
return plaintext

client = kms_v1.KeyManagementServiceClient()
response = client.asymmetric_decrypt(key_name, ciphertext)
return response.plaintext
# [END kms_decrypt_rsa]


# [START kms_encrypt_rsa]
def encryptRSA(plaintext, client, key_path):
def encrypt_rsa(plaintext, key_name):
daniel-sanche marked this conversation as resolved.
Show resolved Hide resolved
"""
Encrypt the input plaintext (bytes) locally using an
'RSA_DECRYPT_OAEP_2048_SHA256' public key retrieved from Cloud KMS

Example key_name:
"projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
/KEY_ID/cryptoKeyVersions/1"

Requires:
cryptography.hazmat.primitives.asymmetric.padding
cryptography.hazmat.primitives.hashes
"""
public_key = getAsymmetricPublicKey(client, key_path)
# get the public key
client = kms_v1.KeyManagementServiceClient()
response = client.get_public_key(key_name)
key_txt = response.pem.encode('ascii')
public_key = serialization.load_pem_public_key(key_txt, default_backend())

# encrypt plaintext
pad = padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None)
Expand All @@ -86,46 +118,53 @@ def encryptRSA(plaintext, client, key_path):


# [START kms_sign_asymmetric]
def signAsymmetric(message, client, key_path):
def sign_asymmetric(message, key_name):
engelke marked this conversation as resolved.
Show resolved Hide resolved
"""
Create a signature for a message using a private key stored on Cloud KMS

Example key_name:
"projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
/KEY_ID/cryptoKeyVersions/1"

Requires:
base64
hashlib
"""
# Note: some key algorithms will require a different hash function
# For example, EC_SIGN_P384_SHA384 requires SHA384
client = kms_v1.KeyManagementServiceClient()
digest_bytes = hashlib.sha256(message).digest()
digest64 = base64.b64encode(digest_bytes)

digest_JSON = {'sha256': digest64.decode('utf-8')}
request = client.projects() \
.locations() \
.keyRings() \
.cryptoKeys() \
.cryptoKeyVersions() \
.asymmetricSign(name=key_path,
body={'digest': digest_JSON})
response = request.execute()
return base64.b64decode(response.get('signature', None))

digest_json = {'sha256': digest_bytes}

response = client.asymmetric_sign(key_name, digest_json)
return response.signature
# [END kms_sign_asymmetric]


# [START kms_verify_signature_rsa]
def verifySignatureRSA(signature, message, client, key_path):
def verify_signature_rsa(signature, message, key_name):
"""
Verify the validity of an 'RSA_SIGN_PSS_2048_SHA256' signature for the
specified message

Example key_name:
"projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
/KEY_ID/cryptoKeyVersions/1"

Requires:
cryptography.exceptions.InvalidSignature
cryptography.hazmat.primitives.asymmetric.padding
cryptography.hazmat.primitives.asymmetric.utils
cryptography.hazmat.primitives.hashes
hashlib
"""
public_key = getAsymmetricPublicKey(client, key_path)
# get the public key
client = kms_v1.KeyManagementServiceClient()
response = client.get_public_key(key_name)
key_txt = response.pem.encode('ascii')
public_key = serialization.load_pem_public_key(key_txt, default_backend())

# get the digest of the message
digest_bytes = hashlib.sha256(message).digest()

try:
Expand All @@ -143,19 +182,29 @@ def verifySignatureRSA(signature, message, client, key_path):


# [START kms_verify_signature_ec]
def verifySignatureEC(signature, message, client, key_path):
def verify_signature_ec(signature, message, key_name):
"""
Verify the validity of an 'EC_SIGN_P256_SHA256' signature
for the specified message

Example key_name:
"projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
/KEY_ID/cryptoKeyVersions/1"

Requires:
cryptography.exceptions.InvalidSignature
cryptography.hazmat.primitives.asymmetric.ec
cryptography.hazmat.primitives.asymmetric.utils
cryptography.hazmat.primitives.hashes
hashlib
"""
public_key = getAsymmetricPublicKey(client, key_path)
# get the public key
client = kms_v1.KeyManagementServiceClient()
response = client.get_public_key(key_name)
key_txt = response.pem.encode('ascii')
public_key = serialization.load_pem_public_key(key_txt, default_backend())

# get the digest of the message
digest_bytes = hashlib.sha256(message).digest()

try:
Expand Down
Loading