13
13
# See the License for the specific language governing permissions and
14
14
# limitations under the License.rom googleapiclient import discovery
15
15
16
- import base64
17
16
import hashlib
18
17
19
18
from cryptography .exceptions import InvalidSignature
20
19
from cryptography .hazmat .backends import default_backend
21
20
from cryptography .hazmat .primitives import hashes , serialization
22
21
from cryptography .hazmat .primitives .asymmetric import ec , padding , utils
23
22
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
+
24
51
25
52
# [START kms_get_asymmetric_public]
26
- def getAsymmetricPublicKey ( client , key_path ):
53
+ def get_asymmetric_public_key ( key_name ):
27
54
"""
28
55
Retrieves the public key from a saved asymmetric key pair on Cloud KMS
29
56
57
+ Example key_name:
58
+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
59
+ /KEY_ID/cryptoKeyVersions/1"
60
+
30
61
Requires:
31
62
cryptography.hazmat.backends.default_backend
32
63
cryptography.hazmat.primitives.serialization
33
64
"""
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' )
42
70
key = serialization .load_pem_public_key (key_txt , default_backend ())
43
71
return key
44
72
# [END kms_get_asymmetric_public]
45
73
46
74
47
75
# [START kms_decrypt_rsa]
48
- def decryptRSA (ciphertext , client , key_path ):
76
+ def decrypt_rsa (ciphertext , key_name ):
49
77
"""
50
78
Decrypt the input ciphertext (bytes) using an
51
79
'RSA_DECRYPT_OAEP_2048_SHA256' private key stored on Cloud KMS
52
80
53
- Requires:
54
- base64
81
+ Example key_name:
82
+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
83
+ /KEY_ID/cryptoKeyVersions/1"
55
84
"""
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
67
89
# [END kms_decrypt_rsa]
68
90
69
91
70
92
# [START kms_encrypt_rsa]
71
- def encryptRSA (plaintext , client , key_path ):
93
+ def encrypt_rsa (plaintext , key_name ):
72
94
"""
73
95
Encrypt the input plaintext (bytes) locally using an
74
96
'RSA_DECRYPT_OAEP_2048_SHA256' public key retrieved from Cloud KMS
75
97
98
+ Example key_name:
99
+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
100
+ /KEY_ID/cryptoKeyVersions/1"
101
+
76
102
Requires:
77
103
cryptography.hazmat.primitives.asymmetric.padding
78
104
cryptography.hazmat.primitives.hashes
79
105
"""
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
81
113
pad = padding .OAEP (mgf = padding .MGF1 (algorithm = hashes .SHA256 ()),
82
114
algorithm = hashes .SHA256 (),
83
115
label = None )
@@ -86,46 +118,53 @@ def encryptRSA(plaintext, client, key_path):
86
118
87
119
88
120
# [START kms_sign_asymmetric]
89
- def signAsymmetric (message , client , key_path ):
121
+ def sign_asymmetric (message , key_name ):
90
122
"""
91
123
Create a signature for a message using a private key stored on Cloud KMS
92
124
125
+ Example key_name:
126
+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
127
+ /KEY_ID/cryptoKeyVersions/1"
128
+
93
129
Requires:
94
- base64
95
130
hashlib
96
131
"""
97
132
# Note: some key algorithms will require a different hash function
98
133
# For example, EC_SIGN_P384_SHA384 requires SHA384
134
+ client = kms_v1 .KeyManagementServiceClient ()
99
135
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
112
141
# [END kms_sign_asymmetric]
113
142
114
143
115
144
# [START kms_verify_signature_rsa]
116
- def verifySignatureRSA (signature , message , client , key_path ):
145
+ def verify_signature_rsa (signature , message , key_name ):
117
146
"""
118
147
Verify the validity of an 'RSA_SIGN_PSS_2048_SHA256' signature for the
119
148
specified message
120
149
150
+ Example key_name:
151
+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
152
+ /KEY_ID/cryptoKeyVersions/1"
153
+
121
154
Requires:
122
155
cryptography.exceptions.InvalidSignature
123
156
cryptography.hazmat.primitives.asymmetric.padding
124
157
cryptography.hazmat.primitives.asymmetric.utils
125
158
cryptography.hazmat.primitives.hashes
126
159
hashlib
127
160
"""
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
129
168
digest_bytes = hashlib .sha256 (message ).digest ()
130
169
131
170
try :
@@ -143,19 +182,29 @@ def verifySignatureRSA(signature, message, client, key_path):
143
182
144
183
145
184
# [START kms_verify_signature_ec]
146
- def verifySignatureEC (signature , message , client , key_path ):
185
+ def verify_signature_ec (signature , message , key_name ):
147
186
"""
148
187
Verify the validity of an 'EC_SIGN_P256_SHA256' signature
149
188
for the specified message
150
189
190
+ Example key_name:
191
+ "projects/PROJECT_ID/locations/global/keyRings/RING_ID/cryptoKeys\
192
+ /KEY_ID/cryptoKeyVersions/1"
193
+
151
194
Requires:
152
195
cryptography.exceptions.InvalidSignature
153
196
cryptography.hazmat.primitives.asymmetric.ec
154
197
cryptography.hazmat.primitives.asymmetric.utils
155
198
cryptography.hazmat.primitives.hashes
156
199
hashlib
157
200
"""
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
159
208
digest_bytes = hashlib .sha256 (message ).digest ()
160
209
161
210
try :
0 commit comments