1313# See the License for the specific language governing permissions and
1414# limitations under the License.rom googleapiclient import discovery
1515
16- import base64
1716import hashlib
1817
1918from cryptography .exceptions import InvalidSignature
2019from cryptography .hazmat .backends import default_backend
2120from cryptography .hazmat .primitives import hashes , serialization
2221from cryptography .hazmat .primitives .asymmetric import ec , padding , utils
2322
23+ from google .cloud import kms_v1
24+ from google .cloud .kms_v1 import enums
25+
26+
27+ # [START kms_create_asymmetric_key]
28+ def create_asymmetric_key (project_id , location_id , key_ring_id , crypto_key_id ):
29+ """Creates an RSA encrypt/decrypt key pair within a specified KeyRing."""
30+
31+ # Creates an API client for the KMS API.
32+ client = kms_v1 .KeyManagementServiceClient ()
33+
34+ # The resource name of the KeyRing associated with the CryptoKey.
35+ parent = client .key_ring_path (project_id , location_id , key_ring_id )
36+
37+ # Create the CryptoKey object template
38+ purpose = enums .CryptoKey .CryptoKeyPurpose .ASYMMETRIC_DECRYPT
39+ algorithm = enums .CryptoKeyVersion .CryptoKeyVersionAlgorithm .\
40+ RSA_DECRYPT_OAEP_2048_SHA256
41+ crypto_key = {'purpose' : purpose ,
42+ 'version_template' : {'algorithm' : algorithm }}
43+
44+ # Create a CryptoKey for the given KeyRing.
45+ response = client .create_crypto_key (parent , crypto_key_id , crypto_key )
46+
47+ print ('Created CryptoKey {}.' .format (response .name ))
48+ return response
49+ # [END kms_create_asymmetric_key]
50+
2451
2552# [START kms_get_asymmetric_public]
26- def getAsymmetricPublicKey ( client , key_path ):
53+ def get_asymmetric_public_key ( key_name ):
2754 """
2855 Retrieves the public key from a saved asymmetric key pair on Cloud KMS
2956
57+ Example key_name:
58+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
59+ /KEY_ID/cryptoKeyVersions/1"
60+
3061 Requires:
3162 cryptography.hazmat.backends.default_backend
3263 cryptography.hazmat.primitives.serialization
3364 """
34- request = client .projects () \
35- .locations () \
36- .keyRings () \
37- .cryptoKeys () \
38- .cryptoKeyVersions () \
39- .getPublicKey (name = key_path )
40- response = request .execute ()
41- key_txt = response ['pem' ].encode ('ascii' )
65+
66+ client = kms_v1 .KeyManagementServiceClient ()
67+ response = client .get_public_key (key_name )
68+
69+ key_txt = response .pem .encode ('ascii' )
4270 key = serialization .load_pem_public_key (key_txt , default_backend ())
4371 return key
4472# [END kms_get_asymmetric_public]
4573
4674
4775# [START kms_decrypt_rsa]
48- def decryptRSA (ciphertext , client , key_path ):
76+ def decrypt_rsa (ciphertext , key_name ):
4977 """
5078 Decrypt the input ciphertext (bytes) using an
5179 'RSA_DECRYPT_OAEP_2048_SHA256' private key stored on Cloud KMS
5280
53- Requires:
54- base64
81+ Example key_name:
82+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
83+ /KEY_ID/cryptoKeyVersions/1"
5584 """
56- request_body = {'ciphertext' : base64 .b64encode (ciphertext ).decode ('utf-8' )}
57- request = client .projects () \
58- .locations () \
59- .keyRings () \
60- .cryptoKeys () \
61- .cryptoKeyVersions () \
62- .asymmetricDecrypt (name = key_path ,
63- body = request_body )
64- response = request .execute ()
65- plaintext = base64 .b64decode (response ['plaintext' ])
66- return plaintext
85+
86+ client = kms_v1 .KeyManagementServiceClient ()
87+ response = client .asymmetric_decrypt (key_name , ciphertext )
88+ return response .plaintext
6789# [END kms_decrypt_rsa]
6890
6991
7092# [START kms_encrypt_rsa]
71- def encryptRSA (plaintext , client , key_path ):
93+ def encrypt_rsa (plaintext , key_name ):
7294 """
7395 Encrypt the input plaintext (bytes) locally using an
7496 'RSA_DECRYPT_OAEP_2048_SHA256' public key retrieved from Cloud KMS
7597
98+ Example key_name:
99+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
100+ /KEY_ID/cryptoKeyVersions/1"
101+
76102 Requires:
77103 cryptography.hazmat.primitives.asymmetric.padding
78104 cryptography.hazmat.primitives.hashes
79105 """
80- public_key = getAsymmetricPublicKey (client , key_path )
106+ # get the public key
107+ client = kms_v1 .KeyManagementServiceClient ()
108+ response = client .get_public_key (key_name )
109+ key_txt = response .pem .encode ('ascii' )
110+ public_key = serialization .load_pem_public_key (key_txt , default_backend ())
111+
112+ # encrypt plaintext
81113 pad = padding .OAEP (mgf = padding .MGF1 (algorithm = hashes .SHA256 ()),
82114 algorithm = hashes .SHA256 (),
83115 label = None )
@@ -86,46 +118,53 @@ def encryptRSA(plaintext, client, key_path):
86118
87119
88120# [START kms_sign_asymmetric]
89- def signAsymmetric (message , client , key_path ):
121+ def sign_asymmetric (message , key_name ):
90122 """
91123 Create a signature for a message using a private key stored on Cloud KMS
92124
125+ Example key_name:
126+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
127+ /KEY_ID/cryptoKeyVersions/1"
128+
93129 Requires:
94- base64
95130 hashlib
96131 """
97132 # Note: some key algorithms will require a different hash function
98133 # For example, EC_SIGN_P384_SHA384 requires SHA384
134+ client = kms_v1 .KeyManagementServiceClient ()
99135 digest_bytes = hashlib .sha256 (message ).digest ()
100- digest64 = base64 .b64encode (digest_bytes )
101-
102- digest_JSON = {'sha256' : digest64 .decode ('utf-8' )}
103- request = client .projects () \
104- .locations () \
105- .keyRings () \
106- .cryptoKeys () \
107- .cryptoKeyVersions () \
108- .asymmetricSign (name = key_path ,
109- body = {'digest' : digest_JSON })
110- response = request .execute ()
111- return base64 .b64decode (response .get ('signature' , None ))
136+
137+ digest_json = {'sha256' : digest_bytes }
138+
139+ response = client .asymmetric_sign (key_name , digest_json )
140+ return response .signature
112141# [END kms_sign_asymmetric]
113142
114143
115144# [START kms_verify_signature_rsa]
116- def verifySignatureRSA (signature , message , client , key_path ):
145+ def verify_signature_rsa (signature , message , key_name ):
117146 """
118147 Verify the validity of an 'RSA_SIGN_PSS_2048_SHA256' signature for the
119148 specified message
120149
150+ Example key_name:
151+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
152+ /KEY_ID/cryptoKeyVersions/1"
153+
121154 Requires:
122155 cryptography.exceptions.InvalidSignature
123156 cryptography.hazmat.primitives.asymmetric.padding
124157 cryptography.hazmat.primitives.asymmetric.utils
125158 cryptography.hazmat.primitives.hashes
126159 hashlib
127160 """
128- public_key = getAsymmetricPublicKey (client , key_path )
161+ # get the public key
162+ client = kms_v1 .KeyManagementServiceClient ()
163+ response = client .get_public_key (key_name )
164+ key_txt = response .pem .encode ('ascii' )
165+ public_key = serialization .load_pem_public_key (key_txt , default_backend ())
166+
167+ # get the digest of the message
129168 digest_bytes = hashlib .sha256 (message ).digest ()
130169
131170 try :
@@ -143,19 +182,29 @@ def verifySignatureRSA(signature, message, client, key_path):
143182
144183
145184# [START kms_verify_signature_ec]
146- def verifySignatureEC (signature , message , client , key_path ):
185+ def verify_signature_ec (signature , message , key_name ):
147186 """
148187 Verify the validity of an 'EC_SIGN_P256_SHA256' signature
149188 for the specified message
150189
190+ Example key_name:
191+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
192+ /KEY_ID/cryptoKeyVersions/1"
193+
151194 Requires:
152195 cryptography.exceptions.InvalidSignature
153196 cryptography.hazmat.primitives.asymmetric.ec
154197 cryptography.hazmat.primitives.asymmetric.utils
155198 cryptography.hazmat.primitives.hashes
156199 hashlib
157200 """
158- public_key = getAsymmetricPublicKey (client , key_path )
201+ # get the public key
202+ client = kms_v1 .KeyManagementServiceClient ()
203+ response = client .get_public_key (key_name )
204+ key_txt = response .pem .encode ('ascii' )
205+ public_key = serialization .load_pem_public_key (key_txt , default_backend ())
206+
207+ # get the digest of the message
159208 digest_bytes = hashlib .sha256 (message ).digest ()
160209
161210 try :
0 commit comments