Skip to content

Commit

Permalink
KMS: Updated for new client library (#1903)
Browse files Browse the repository at this point in the history
* updated kms samples to use new gapic client library
  • Loading branch information
daniel-sanche authored Jan 7, 2019
1 parent 544aafa commit 6f9eacf
Show file tree
Hide file tree
Showing 8 changed files with 573 additions and 612 deletions.
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)

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):
"""
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):
"""
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

0 comments on commit 6f9eacf

Please sign in to comment.