1*e7b1675dSTing-Kang Chang# Tink for Python HOW-TO 2*e7b1675dSTing-Kang Chang 3*e7b1675dSTing-Kang ChangThis document presents instructions and Python code snippets for common tasks in 4*e7b1675dSTing-Kang Chang[Tink](https://github.com/google/tink). 5*e7b1675dSTing-Kang Chang 6*e7b1675dSTing-Kang Chang## Setup instructions 7*e7b1675dSTing-Kang Chang 8*e7b1675dSTing-Kang ChangTink requires Python 3.7 or above. 9*e7b1675dSTing-Kang Chang 10*e7b1675dSTing-Kang ChangThe simplest way is to install a binary release from 11*e7b1675dSTing-Kang Chang[PyPi](https://pypi.org/project/tink/): 12*e7b1675dSTing-Kang Chang 13*e7b1675dSTing-Kang Chang```shell 14*e7b1675dSTing-Kang Changpip3 install tink 15*e7b1675dSTing-Kang Chang``` 16*e7b1675dSTing-Kang Chang 17*e7b1675dSTing-Kang ChangCurrently, the following set of binary wheels are published: 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Chang* Linux 20*e7b1675dSTing-Kang Chang * Python 3.7 21*e7b1675dSTing-Kang Chang * Python 3.8 22*e7b1675dSTing-Kang Chang * Python 3.9 23*e7b1675dSTing-Kang Chang* macOS 24*e7b1675dSTing-Kang Chang * Python 3.7 25*e7b1675dSTing-Kang Chang * Python 3.8 26*e7b1675dSTing-Kang Chang * Python 3.9 27*e7b1675dSTing-Kang Chang 28*e7b1675dSTing-Kang ChangIn addition to the binary wheels, a source distribution is also published. If 29*e7b1675dSTing-Kang Chang`pip` does not find a suitable binary wheel for your environment, it will fall 30*e7b1675dSTing-Kang Changback to building the project using the source distribution. This process has the 31*e7b1675dSTing-Kang Changsame requirements as building from source instructions below. 32*e7b1675dSTing-Kang Chang 33*e7b1675dSTing-Kang Chang### Common setup issues 34*e7b1675dSTing-Kang Chang 35*e7b1675dSTing-Kang Chang* If you get an error regarding the root certs when using the GCP KMS 36*e7b1675dSTing-Kang Chang integration, you will have to install the 37*e7b1675dSTing-Kang Chang [root certs](https://github.com/googleapis/google-cloud-cpp/blob/master/google/cloud/bigtable/examples/README.md#configure-grpc-root-certificates). 38*e7b1675dSTing-Kang Chang 39*e7b1675dSTing-Kang Chang## Building from source 40*e7b1675dSTing-Kang Chang 41*e7b1675dSTing-Kang ChangTink currently supports two build systems for use with Python: 42*e7b1675dSTing-Kang Chang 43*e7b1675dSTing-Kang Chang* [Bazel](https://bazel.build/) 44*e7b1675dSTing-Kang Chang* Setuptools to create a Python package 45*e7b1675dSTing-Kang Chang 46*e7b1675dSTing-Kang ChangNote that in both cases [Bazel](https://bazel.build/) is required, as it is 47*e7b1675dSTing-Kang Changneeded to compile the wrapper around the C++ implementation which uses 48*e7b1675dSTing-Kang Chang[pybind11](https://github.com/pybind/pybind11). 49*e7b1675dSTing-Kang Chang 50*e7b1675dSTing-Kang Chang### Build with Bazel 51*e7b1675dSTing-Kang Chang 52*e7b1675dSTing-Kang ChangTo build the Python implementation: 53*e7b1675dSTing-Kang Chang 54*e7b1675dSTing-Kang Chang```shell 55*e7b1675dSTing-Kang Changcd python 56*e7b1675dSTing-Kang Changbazel build ... 57*e7b1675dSTing-Kang Chang``` 58*e7b1675dSTing-Kang Chang 59*e7b1675dSTing-Kang Chang### Build a Python package using pip 60*e7b1675dSTing-Kang Chang 61*e7b1675dSTing-Kang ChangA setup script is provided which allows building a Python package using pip. 62*e7b1675dSTing-Kang Chang 63*e7b1675dSTing-Kang ChangThe setup script requires: 64*e7b1675dSTing-Kang Chang 65*e7b1675dSTing-Kang Chang* Bazel 66*e7b1675dSTing-Kang Chang* [protobuf compiler](https://github.com/protocolbuffers/protobuf#protocol-compiler-installation). 67*e7b1675dSTing-Kang Chang 68*e7b1675dSTing-Kang ChangTo build and install the Python package: 69*e7b1675dSTing-Kang Chang 70*e7b1675dSTing-Kang Chang```shell 71*e7b1675dSTing-Kang Changcd python 72*e7b1675dSTing-Kang Changpip3 install . 73*e7b1675dSTing-Kang Chang``` 74*e7b1675dSTing-Kang Chang 75*e7b1675dSTing-Kang Chang### Running tests 76*e7b1675dSTing-Kang Chang 77*e7b1675dSTing-Kang ChangTo run all tests, you can: 78*e7b1675dSTing-Kang Chang 79*e7b1675dSTing-Kang Chang```shell 80*e7b1675dSTing-Kang Changcd python 81*e7b1675dSTing-Kang Changbazel test ... 82*e7b1675dSTing-Kang Chang``` 83*e7b1675dSTing-Kang Chang 84*e7b1675dSTing-Kang Chang## Initializing Tink 85*e7b1675dSTing-Kang Chang 86*e7b1675dSTing-Kang ChangTink provides customizable initialization, which allows for choosing specific 87*e7b1675dSTing-Kang Changimplementations (identified by _key types_) of desired primitives. This 88*e7b1675dSTing-Kang Changinitialization happens via _registration_ of the implementations. 89*e7b1675dSTing-Kang Chang 90*e7b1675dSTing-Kang ChangFor example, if you want to use all standard implementations of all primitives 91*e7b1675dSTing-Kang Changin the current release of Tink, the initialization would look as follows: 92*e7b1675dSTing-Kang Chang 93*e7b1675dSTing-Kang Chang```python 94*e7b1675dSTing-Kang Changimport tink 95*e7b1675dSTing-Kang Changfrom tink import tink_config 96*e7b1675dSTing-Kang Changtink_config.register() 97*e7b1675dSTing-Kang Chang``` 98*e7b1675dSTing-Kang Chang 99*e7b1675dSTing-Kang ChangTo use standard implementations of only one primitive, say AEAD: 100*e7b1675dSTing-Kang Chang 101*e7b1675dSTing-Kang Chang```python 102*e7b1675dSTing-Kang Changimport tink 103*e7b1675dSTing-Kang Changfrom tink import aead 104*e7b1675dSTing-Kang Changaead.register() 105*e7b1675dSTing-Kang Chang``` 106*e7b1675dSTing-Kang Chang 107*e7b1675dSTing-Kang ChangThe registration of custom key managers can proceed directly via 108*e7b1675dSTing-Kang Changthe `core.Registry` class: 109*e7b1675dSTing-Kang Chang 110*e7b1675dSTing-Kang Chang```python 111*e7b1675dSTing-Kang Changimport tink 112*e7b1675dSTing-Kang Changfrom tink import core 113*e7b1675dSTing-Kang Changcore.Registry.register_key_manager(CustomAeadKeyManager()) 114*e7b1675dSTing-Kang Chang``` 115*e7b1675dSTing-Kang Chang 116*e7b1675dSTing-Kang Chang## Generating new keys and keysets 117*e7b1675dSTing-Kang Chang 118*e7b1675dSTing-Kang ChangEach `KeyManager` implementation provides a `new_key_data(key_template)` method 119*e7b1675dSTing-Kang Changthat generates new keys of the corresponding key type. However, to avoid 120*e7b1675dSTing-Kang Changaccidental leakage of sensitive key material you should avoid mixing key(set) 121*e7b1675dSTing-Kang Changgeneration with key(set) usage in code. 122*e7b1675dSTing-Kang Chang 123*e7b1675dSTing-Kang ChangTo support the separation between these activities Tink package provides a 124*e7b1675dSTing-Kang Changcommand-line tool called [Tinkey](TINKEY.md), which can be used for common key 125*e7b1675dSTing-Kang Changmanagement tasks. 126*e7b1675dSTing-Kang Chang 127*e7b1675dSTing-Kang ChangStill, if there is a need to generate a KeysetHandle with fresh key material 128*e7b1675dSTing-Kang Changdirectly in Python code, you can use `tink.new_keyset_handle`: 129*e7b1675dSTing-Kang Chang 130*e7b1675dSTing-Kang Chang```python 131*e7b1675dSTing-Kang Changimport tink 132*e7b1675dSTing-Kang Changfrom tink import aead 133*e7b1675dSTing-Kang Chang 134*e7b1675dSTing-Kang Changkey_template = aead.aead_key_templates.AES128_EAX 135*e7b1675dSTing-Kang Changkeyset_handle = tink.new_keyset_handle(key_template) 136*e7b1675dSTing-Kang Chang# use the keyset... 137*e7b1675dSTing-Kang Chang``` 138*e7b1675dSTing-Kang Chang 139*e7b1675dSTing-Kang Changwhere `key_template` can be obtained from util classes corresponding to Tink 140*e7b1675dSTing-Kang Changprimitives, e.g. 141*e7b1675dSTing-Kang Chang[mac_key_templates](https://github.com/google/tink/blob/master/python/tink/mac/_mac_key_templates.py), 142*e7b1675dSTing-Kang Chang[aead_key_templates](https://github.com/google/tink/blob/master/python/tink/aead/_aead_key_templates.py), 143*e7b1675dSTing-Kang Changor 144*e7b1675dSTing-Kang Chang[hybrid_key_templates](https://github.com/google/tink/blob/master/python/tink/hybrid/_hybrid_key_templates.py). 145*e7b1675dSTing-Kang Chang 146*e7b1675dSTing-Kang Chang## Loading existing keysets 147*e7b1675dSTing-Kang Chang 148*e7b1675dSTing-Kang ChangTo load encrypted keysets, use `tink.read_keyset_handle` 149*e7b1675dSTing-Kang Changand an appropriate [`KeysetReader`](https://github.com/google/tink/blob/master/python/tink/_keyset_reader.py), 150*e7b1675dSTing-Kang Changdepending on the wire format of the stored keyset, for example a 151*e7b1675dSTing-Kang Chang`tink.BinaryKeysetReader` or a `tink.JsonKeysetReader`. 152*e7b1675dSTing-Kang Chang 153*e7b1675dSTing-Kang Chang```python 154*e7b1675dSTing-Kang Changimport tink 155*e7b1675dSTing-Kang Chang 156*e7b1675dSTing-Kang Changjson_encrypted_keyset = ... 157*e7b1675dSTing-Kang Changreader = tink.JsonKeysetReader(json_encrypted_keyset) 158*e7b1675dSTing-Kang Changkeyset_handle = tink.read_keyset_handle(reader, master_key_aead) 159*e7b1675dSTing-Kang Chang``` 160*e7b1675dSTing-Kang Chang 161*e7b1675dSTing-Kang ChangTo load cleartext keysets, use [`cleartext_keyset_handle`](https://github.com/google/tink/blob/master/python/tink/cleartext_keyset_handle.py) 162*e7b1675dSTing-Kang Changand an appropriate `KeysetReader`. 163*e7b1675dSTing-Kang Chang 164*e7b1675dSTing-Kang Chang```python 165*e7b1675dSTing-Kang Changimport tink 166*e7b1675dSTing-Kang Changfrom tink import cleartext_keyset_handle 167*e7b1675dSTing-Kang Chang 168*e7b1675dSTing-Kang Changjson_keyset = ... 169*e7b1675dSTing-Kang Changreader = tink.JsonKeysetReader(json_keyset) 170*e7b1675dSTing-Kang Changkeyset_handle = cleartext_keyset_handle.read(reader) 171*e7b1675dSTing-Kang Chang``` 172*e7b1675dSTing-Kang Chang## Obtaining and using primitives 173*e7b1675dSTing-Kang Chang 174*e7b1675dSTing-Kang Chang[_Primitives_](PRIMITIVES.md) represent cryptographic operations offered by 175*e7b1675dSTing-Kang ChangTink, hence they form the core of the Tink API. A primitive is just an interface 176*e7b1675dSTing-Kang Changthat specifies what operations are offered by the primitive. A primitive can 177*e7b1675dSTing-Kang Changhave multiple implementations, and you choose a desired implementation by using 178*e7b1675dSTing-Kang Changa key of corresponding type (see [this 179*e7b1675dSTing-Kang Changsection](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for further details). 180*e7b1675dSTing-Kang Chang 181*e7b1675dSTing-Kang ChangTink for Python supports the same primitives as Tink for C++. A list of 182*e7b1675dSTing-Kang Changprimitives and their implementations currently supported by Tink in C++ can be 183*e7b1675dSTing-Kang Changfound [here](PRIMITIVES.md#c). 184*e7b1675dSTing-Kang Chang 185*e7b1675dSTing-Kang ChangYou obtain a primitive by calling the method `primitive` of the `KeysetHandle`. 186*e7b1675dSTing-Kang Chang 187*e7b1675dSTing-Kang Chang### Symmetric key encryption 188*e7b1675dSTing-Kang Chang 189*e7b1675dSTing-Kang ChangYou can obtain and use an [AEAD (Authenticated Encryption with Associated 190*e7b1675dSTing-Kang ChangData)](PRIMITIVES.md#authenticated-encryption-with-associated-data) primitive to 191*e7b1675dSTing-Kang Changencrypt or decrypt data: 192*e7b1675dSTing-Kang Chang 193*e7b1675dSTing-Kang Chang```python 194*e7b1675dSTing-Kang Changimport tink 195*e7b1675dSTing-Kang Changfrom tink import aead 196*e7b1675dSTing-Kang Chang 197*e7b1675dSTing-Kang Changplaintext = b'your data...' 198*e7b1675dSTing-Kang Changassociated_data = b'context' 199*e7b1675dSTing-Kang Chang 200*e7b1675dSTing-Kang Chang# Register all AEAD primitives 201*e7b1675dSTing-Kang Changaead.register() 202*e7b1675dSTing-Kang Chang 203*e7b1675dSTing-Kang Chang# 1. Get a handle to the key material. 204*e7b1675dSTing-Kang Changkeyset_handle = tink.new_keyset_handle(aead.aead_key_templates.AES256_GCM) 205*e7b1675dSTing-Kang Chang 206*e7b1675dSTing-Kang Chang# 2. Get the primitive. 207*e7b1675dSTing-Kang Changaead_primitive = keyset_handle.primitive(aead.Aead) 208*e7b1675dSTing-Kang Chang 209*e7b1675dSTing-Kang Chang# 3. Use the primitive. 210*e7b1675dSTing-Kang Changciphertext = aead_primitive.encrypt(plaintext, associated_data) 211*e7b1675dSTing-Kang Chang``` 212*e7b1675dSTing-Kang Chang 213*e7b1675dSTing-Kang Chang### Deterministic symmetric key encryption 214*e7b1675dSTing-Kang Chang 215*e7b1675dSTing-Kang ChangYou can obtain and use a 216*e7b1675dSTing-Kang Chang[DeterministicAEAD (Deterministic Authenticated Encryption with Associated Data](PRIMITIVES.md#deterministic-authenticated-encryption-with-associated-data) 217*e7b1675dSTing-Kang Changprimitive to encrypt or decrypt data: 218*e7b1675dSTing-Kang Chang 219*e7b1675dSTing-Kang Chang```python 220*e7b1675dSTing-Kang Changimport tink 221*e7b1675dSTing-Kang Changfrom tink import daead 222*e7b1675dSTing-Kang Chang 223*e7b1675dSTing-Kang Changplaintext = b'your data...' 224*e7b1675dSTing-Kang Changassociated_data = b'context' 225*e7b1675dSTing-Kang Chang 226*e7b1675dSTing-Kang Chang# Register all deterministic AEAD primitives 227*e7b1675dSTing-Kang Changdaead.register() 228*e7b1675dSTing-Kang Chang 229*e7b1675dSTing-Kang Chang# 1. Get a handle to the key material. 230*e7b1675dSTing-Kang Changkeyset_handle = tink.new_keyset_handle(daead.deterministic_aead_key_templates.AES256_SIV) 231*e7b1675dSTing-Kang Chang 232*e7b1675dSTing-Kang Chang# 2. Get the primitive. 233*e7b1675dSTing-Kang Changdaead_primitive = keyset_handle.primitive(daead.DeterministicAead) 234*e7b1675dSTing-Kang Chang 235*e7b1675dSTing-Kang Chang# 3. Use the primitive. 236*e7b1675dSTing-Kang Changciphertext = daead_primitive.encrypt_deterministically(plaintext, associated_data) 237*e7b1675dSTing-Kang Chang``` 238*e7b1675dSTing-Kang Chang 239*e7b1675dSTing-Kang Chang### Symmetric key encryption of streaming data 240*e7b1675dSTing-Kang Chang 241*e7b1675dSTing-Kang ChangYou can obtain and use a 242*e7b1675dSTing-Kang Chang[Streaming AEAD (Streaming Authenticated Encryption with Associated Data)](PRIMITIVES.md#streaming-authenticated-encryption-with-associated-data) 243*e7b1675dSTing-Kang Changprimitive to encrypt or decrypt data streams: 244*e7b1675dSTing-Kang Chang 245*e7b1675dSTing-Kang Chang```python 246*e7b1675dSTing-Kang Changimport tink 247*e7b1675dSTing-Kang Changfrom tink import streaming_aead 248*e7b1675dSTing-Kang Chang 249*e7b1675dSTing-Kang Changlong_plaintext = b'your data...' 250*e7b1675dSTing-Kang Changassociated_data = b'context' 251*e7b1675dSTing-Kang Chang 252*e7b1675dSTing-Kang Chang# Register all streaming AEAD primitives 253*e7b1675dSTing-Kang Changstreaming_aead.register() 254*e7b1675dSTing-Kang Chang 255*e7b1675dSTing-Kang Chang# 1. Get a handle to the key material 256*e7b1675dSTing-Kang Changkeyset_handle = tink.new_keyset_handle(streaming_aead.streaming_aead_key_templates.AES256_CTR_HMAC_SHA256_4KB) 257*e7b1675dSTing-Kang Chang 258*e7b1675dSTing-Kang Chang# 2. Get the primitive. 259*e7b1675dSTing-Kang Changstreaming_aead_primitive = keyset_handle.primitive(streaming_aead.StreamingAead) 260*e7b1675dSTing-Kang Chang 261*e7b1675dSTing-Kang Chang# 3. Use the primitive. 262*e7b1675dSTing-Kang Changoutput_file = open("ciphertext.out", 'wb') 263*e7b1675dSTing-Kang Changwith streaming_aead_primitive.new_encrypting_stream(output_file, associated_data) as enc_stream: 264*e7b1675dSTing-Kang Chang bytes_written = enc_stream.write(long_plaintext) 265*e7b1675dSTing-Kang Chang``` 266*e7b1675dSTing-Kang Chang 267*e7b1675dSTing-Kang Chang### Message Authentication Code 268*e7b1675dSTing-Kang Chang 269*e7b1675dSTing-Kang ChangYou can compute or verify a 270*e7b1675dSTing-Kang Chang[MAC (Message Authentication Code)](PRIMITIVES.md#message-authentication-code): 271*e7b1675dSTing-Kang Chang 272*e7b1675dSTing-Kang Chang```python 273*e7b1675dSTing-Kang Changimport tink 274*e7b1675dSTing-Kang Changfrom tink import mac 275*e7b1675dSTing-Kang Chang 276*e7b1675dSTing-Kang Changdata = b'your data...' 277*e7b1675dSTing-Kang Chang 278*e7b1675dSTing-Kang Chang# Register all MAC primitives 279*e7b1675dSTing-Kang Changmac.register() 280*e7b1675dSTing-Kang Chang 281*e7b1675dSTing-Kang Chang# 1. Get a handle to the key material. 282*e7b1675dSTing-Kang Changkeyset_handle = tink.new_keyset_handle(mac.mac_key_templates.HMAC_SHA256_128BITTAG) 283*e7b1675dSTing-Kang Chang 284*e7b1675dSTing-Kang Chang# 2. Get the primitive. 285*e7b1675dSTing-Kang Changmac_primitive = keyset_handle.primitive(mac.Mac) 286*e7b1675dSTing-Kang Chang 287*e7b1675dSTing-Kang Chang# 3. Use the primitive to compute a tag, 288*e7b1675dSTing-Kang Changtag = mac_primitive.compute_mac(data) 289*e7b1675dSTing-Kang Chang 290*e7b1675dSTing-Kang Chang# ... or to verify a tag. 291*e7b1675dSTing-Kang Changmac_primitive.verify_mac(tag, data) 292*e7b1675dSTing-Kang Chang``` 293*e7b1675dSTing-Kang Chang 294*e7b1675dSTing-Kang Chang### Hybrid Encryption 295*e7b1675dSTing-Kang Chang 296*e7b1675dSTing-Kang ChangTo encrypt or decrypt using 297*e7b1675dSTing-Kang Chang[a combination of public key encryption and symmetric key encryption](PRIMITIVES.md#hybrid-encryption) 298*e7b1675dSTing-Kang Changone can use the following: 299*e7b1675dSTing-Kang Chang 300*e7b1675dSTing-Kang Chang```python 301*e7b1675dSTing-Kang Changimport tink 302*e7b1675dSTing-Kang Changfrom tink import hybrid 303*e7b1675dSTing-Kang Chang 304*e7b1675dSTing-Kang Changplaintext = b'your data...' 305*e7b1675dSTing-Kang Changcontext = b'context' 306*e7b1675dSTing-Kang Chang 307*e7b1675dSTing-Kang Chang# Register all Hybrid primitives 308*e7b1675dSTing-Kang Changhybrid.register() 309*e7b1675dSTing-Kang Chang 310*e7b1675dSTing-Kang Chang# 1. Generate the private key material. 311*e7b1675dSTing-Kang Changprivate_keyset_handle = tink.new_keyset_handle(hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM) 312*e7b1675dSTing-Kang Chang 313*e7b1675dSTing-Kang Chang# Obtain the public key material. 314*e7b1675dSTing-Kang Changpublic_keyset_handle = private_keyset_handle.public_keyset_handle() 315*e7b1675dSTing-Kang Chang 316*e7b1675dSTing-Kang Chang# Encryption 317*e7b1675dSTing-Kang Chang 318*e7b1675dSTing-Kang Chang# 2. Get the primitive. 319*e7b1675dSTing-Kang Changhybrid_encrypt = public_keyset_handle.primitive(hybrid.HybridEncrypt) 320*e7b1675dSTing-Kang Chang 321*e7b1675dSTing-Kang Chang# 3. Use the primitive. 322*e7b1675dSTing-Kang Changciphertext = hybrid_encrypt.encrypt(plaintext, context) 323*e7b1675dSTing-Kang Chang 324*e7b1675dSTing-Kang Chang# Decryption 325*e7b1675dSTing-Kang Chang 326*e7b1675dSTing-Kang Chang# 2. Get the primitive. 327*e7b1675dSTing-Kang Changhybrid_decrypt = private_keyset_handle.primitive(hybrid.HybridDecrypt) 328*e7b1675dSTing-Kang Chang 329*e7b1675dSTing-Kang Chang# 3. Use the primitive. 330*e7b1675dSTing-Kang Changplaintext = hybrid_decrypt.decrypt(ciphertext, context) 331*e7b1675dSTing-Kang Chang``` 332*e7b1675dSTing-Kang Chang 333*e7b1675dSTing-Kang Chang### Digital Signatures 334*e7b1675dSTing-Kang Chang 335*e7b1675dSTing-Kang ChangYou can sign or verify using a 336*e7b1675dSTing-Kang Chang[digital signature](PRIMITIVES.md#digital-signatures): 337*e7b1675dSTing-Kang Chang 338*e7b1675dSTing-Kang Chang```python 339*e7b1675dSTing-Kang Changimport tink 340*e7b1675dSTing-Kang Changfrom tink import signature 341*e7b1675dSTing-Kang Chang 342*e7b1675dSTing-Kang Chang# Register key manager for signatures 343*e7b1675dSTing-Kang Changsignature.register() 344*e7b1675dSTing-Kang Chang 345*e7b1675dSTing-Kang Chang# Signing 346*e7b1675dSTing-Kang Chang# 1. Generate the private key material. 347*e7b1675dSTing-Kang Changkeyset_handle = tink.new_keyset_handle(signature.signature_key_templates.ED25519) 348*e7b1675dSTing-Kang Chang 349*e7b1675dSTing-Kang Chang# 2. Get the primitive. 350*e7b1675dSTing-Kang Changsigner = keyset_handle.primitive(signature.PublicKeySign) 351*e7b1675dSTing-Kang Chang 352*e7b1675dSTing-Kang Chang# 3. Use the primitive to sign. 353*e7b1675dSTing-Kang Changsignature_data = signer.sign(b'your data') 354*e7b1675dSTing-Kang Chang 355*e7b1675dSTing-Kang Chang# Verifying 356*e7b1675dSTing-Kang Chang# 1. Obtain the public key material. 357*e7b1675dSTing-Kang Changpublic_keyset_handle = keyset_handle.public_keyset_handle() 358*e7b1675dSTing-Kang Chang 359*e7b1675dSTing-Kang Chang# 2. Get the primitive. 360*e7b1675dSTing-Kang Changverifier = public_keyset_handle.primitive(signature.PublicKeyVerify) 361*e7b1675dSTing-Kang Chang 362*e7b1675dSTing-Kang Chang# 3. Use the primitive to verify. 363*e7b1675dSTing-Kang Changverifier.verify(signature_data, b'your data') 364*e7b1675dSTing-Kang Chang``` 365*e7b1675dSTing-Kang Chang 366*e7b1675dSTing-Kang Chang### Envelope encryption 367*e7b1675dSTing-Kang Chang 368*e7b1675dSTing-Kang ChangVia the AEAD interface, Tink supports 369*e7b1675dSTing-Kang Chang[envelope encryption](KEY-MANAGEMENT.md#envelope-encryption). 370*e7b1675dSTing-Kang Chang 371*e7b1675dSTing-Kang ChangFor example, you can perform envelope encryption with a Google Cloud KMS key at 372*e7b1675dSTing-Kang Chang`gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar` 373*e7b1675dSTing-Kang Changusing the credentials in `credentials.json` as follows: 374*e7b1675dSTing-Kang Chang 375*e7b1675dSTing-Kang Chang```python 376*e7b1675dSTing-Kang Changimport tink 377*e7b1675dSTing-Kang Changfrom tink import aead 378*e7b1675dSTing-Kang Changfrom tink.integration import gcpkms 379*e7b1675dSTing-Kang Chang 380*e7b1675dSTing-Kang Changkey_uri = 'gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar' 381*e7b1675dSTing-Kang Changgcp_credentials = 'credentials.json' 382*e7b1675dSTing-Kang Chang 383*e7b1675dSTing-Kang Changplaintext = b'your data...' 384*e7b1675dSTing-Kang Changassociated_data = b'context' 385*e7b1675dSTing-Kang Chang 386*e7b1675dSTing-Kang Chang# Read the GCP credentials and setup client 387*e7b1675dSTing-Kang Changtry: 388*e7b1675dSTing-Kang Chang gcp_client = gcpkms.GcpKmsClient(key_uri, gcp_credentials) 389*e7b1675dSTing-Kang Chang gcp_aead = gcp_client.get_aead(key_uri) 390*e7b1675dSTing-Kang Changexcept tink.TinkError as e: 391*e7b1675dSTing-Kang Chang logging.error('Error initializing GCP client: %s', e) 392*e7b1675dSTing-Kang Chang return 1 393*e7b1675dSTing-Kang Chang 394*e7b1675dSTing-Kang Chang# Create envelope AEAD primitive using AES256 GCM for encrypting the data 395*e7b1675dSTing-Kang Changtry: 396*e7b1675dSTing-Kang Chang key_template = aead.aead_key_templates.AES256_GCM 397*e7b1675dSTing-Kang Chang env_aead = aead.KmsEnvelopeAead(key_template, gcp_aead) 398*e7b1675dSTing-Kang Changexcept tink.TinkError as e: 399*e7b1675dSTing-Kang Chang logging.error('Error creating primitive: %s', e) 400*e7b1675dSTing-Kang Chang return 1 401*e7b1675dSTing-Kang Chang 402*e7b1675dSTing-Kang Chang# Use env_aead to encrypt data 403*e7b1675dSTing-Kang Changciphertext = env_aead.encrypt(plaintext, associated_data) 404*e7b1675dSTing-Kang Chang``` 405