xref: /aosp_15_r20/external/tink/docs/PYTHON-HOWTO.md (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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