xref: /aosp_15_r20/external/tink/docs/OBJC-HOWTO.md (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang# Tink for Obj-C HOW-TO
2*e7b1675dSTing-Kang Chang
3*e7b1675dSTing-Kang ChangThis document contains instructions and Obj-C 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 is released as a [Cocoapod](https://cocoapods.org/). It can be installed by
9*e7b1675dSTing-Kang Changusing the pod command as described below, which is the recommended way to use
10*e7b1675dSTing-Kang ChangTink.
11*e7b1675dSTing-Kang Chang
12*e7b1675dSTing-Kang ChangWe also provide step-by-step instructions on building and using Tink from
13*e7b1675dSTing-Kang Changsource.
14*e7b1675dSTing-Kang Chang
15*e7b1675dSTing-Kang Chang#### Supported platforms
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Chang * iOS 9.0 or newer
18*e7b1675dSTing-Kang Chang * Xcode 9.2 or newer
19*e7b1675dSTing-Kang Chang
20*e7b1675dSTing-Kang Chang### Installing via Cocoapods
21*e7b1675dSTing-Kang Chang
22*e7b1675dSTing-Kang Chang1. Change into the directory that contains your Xcode project.
23*e7b1675dSTing-Kang Chang
24*e7b1675dSTing-Kang Chang   ```sh
25*e7b1675dSTing-Kang Chang   cd /path/to/your/Xcode project/
26*e7b1675dSTing-Kang Chang   ```
27*e7b1675dSTing-Kang Chang
28*e7b1675dSTing-Kang Chang2. Initialize Cocoapods.
29*e7b1675dSTing-Kang Chang
30*e7b1675dSTing-Kang Chang   ```sh
31*e7b1675dSTing-Kang Chang   pod init
32*e7b1675dSTing-Kang Chang   ```
33*e7b1675dSTing-Kang Chang
34*e7b1675dSTing-Kang Chang   This command creates a file called Podfile.
35*e7b1675dSTing-Kang Chang
36*e7b1675dSTing-Kang Chang3. Edit the Podfile.
37*e7b1675dSTing-Kang Chang
38*e7b1675dSTing-Kang Chang   For the current stable release, add the following line:
39*e7b1675dSTing-Kang Chang
40*e7b1675dSTing-Kang Chang   ```
41*e7b1675dSTing-Kang Chang   pod 'Tink'
42*e7b1675dSTing-Kang Chang   ```
43*e7b1675dSTing-Kang Chang
44*e7b1675dSTing-Kang Chang   For a particular version, use a line like the following instead:
45*e7b1675dSTing-Kang Chang
46*e7b1675dSTing-Kang Chang   ```
47*e7b1675dSTing-Kang Chang   pod 'Tink', '1.2.0-rc2'
48*e7b1675dSTing-Kang Chang   ```
49*e7b1675dSTing-Kang Chang
50*e7b1675dSTing-Kang Chang   Note: Replace 1.2.0-rc2 with the pre-release version you want to install.
51*e7b1675dSTing-Kang Chang
52*e7b1675dSTing-Kang Chang4. Install the pod.
53*e7b1675dSTing-Kang Chang
54*e7b1675dSTing-Kang Chang  ```sh
55*e7b1675dSTing-Kang Chang  $ pod install
56*e7b1675dSTing-Kang Chang  ```
57*e7b1675dSTing-Kang Chang
58*e7b1675dSTing-Kang Chang5. Open the newly generated .xcworkspace and start using Tink.
59*e7b1675dSTing-Kang Chang
60*e7b1675dSTing-Kang Chang   You can import the umbrella header:
61*e7b1675dSTing-Kang Chang
62*e7b1675dSTing-Kang Chang   ```objc
63*e7b1675dSTing-Kang Chang   #import "Tink/Tink.h"
64*e7b1675dSTing-Kang Chang   ```
65*e7b1675dSTing-Kang Chang
66*e7b1675dSTing-Kang Chang   Or individual headers:
67*e7b1675dSTing-Kang Chang
68*e7b1675dSTing-Kang Chang   ```objc
69*e7b1675dSTing-Kang Chang   #import "Tink/TINKAeadConfig.h"
70*e7b1675dSTing-Kang Chang   #import "Tink/TINKAeadKeyTemplate.h"
71*e7b1675dSTing-Kang Chang   #import "Tink/TINKAead.h"
72*e7b1675dSTing-Kang Chang   ```
73*e7b1675dSTing-Kang Chang
74*e7b1675dSTing-Kang Chang### Installing from source
75*e7b1675dSTing-Kang Chang
76*e7b1675dSTing-Kang Chang#### Prerequisites
77*e7b1675dSTing-Kang Chang
78*e7b1675dSTing-Kang ChangTo install Tink from the source code, the following prerequisites must be
79*e7b1675dSTing-Kang Changinstalled:
80*e7b1675dSTing-Kang Chang
81*e7b1675dSTing-Kang Chang*   [git](https://git-scm.com/) - to download the source of Tink
82*e7b1675dSTing-Kang Chang*   [Bazel](https://www.bazel.build) v0.15.0 or newer - to build Tink
83*e7b1675dSTing-Kang Chang
84*e7b1675dSTing-Kang Chang#### Step-by-step instructions
85*e7b1675dSTing-Kang Chang
86*e7b1675dSTing-Kang Chang1.  Clone Tink from GitHub.
87*e7b1675dSTing-Kang Chang
88*e7b1675dSTing-Kang Chang    ```sh
89*e7b1675dSTing-Kang Chang    git clone https://github.com/google/tink/
90*e7b1675dSTing-Kang Chang    ```
91*e7b1675dSTing-Kang Chang
92*e7b1675dSTing-Kang Chang2.  Build the library and generate a static iOS framework.
93*e7b1675dSTing-Kang Chang
94*e7b1675dSTing-Kang Chang    ```sh
95*e7b1675dSTing-Kang Chang    cd tink
96*e7b1675dSTing-Kang Chang    export XCODE_VERSION=9.2
97*e7b1675dSTing-Kang Chang    export IOS_SDK=11.2
98*e7b1675dSTing-Kang Chang    bazel build -c opt --ios_multi_cpus=i386,x86_64,armv7,arm64 --xcode_version="${XCODE_VERSION}" --ios_sdk_version="${IOS_SDK}" //objc:Tink_framework
99*e7b1675dSTing-Kang Chang    ```
100*e7b1675dSTing-Kang Chang
101*e7b1675dSTing-Kang Chang    Adjust the following options according to your build environment:
102*e7b1675dSTing-Kang Chang
103*e7b1675dSTing-Kang Chang    *   Set `XCODE_VERSION` to the Xcode version you are using to build your
104*e7b1675dSTing-Kang Chang        application.
105*e7b1675dSTing-Kang Chang
106*e7b1675dSTing-Kang Chang    *   Set `IOS_SDK` to the version of the iOS SDK you are using in your
107*e7b1675dSTing-Kang Chang        application.
108*e7b1675dSTing-Kang Chang
109*e7b1675dSTing-Kang Chang    *   The option `ios_multi_cpus` is used to generate a fat library that
110*e7b1675dSTing-Kang Chang        includes multiple architectures. Before submitting your application to
111*e7b1675dSTing-Kang Chang        the App Store you should generate a framework that includes only the ARM
112*e7b1675dSTing-Kang Chang        architectures and link it to your binary.
113*e7b1675dSTing-Kang Chang
114*e7b1675dSTing-Kang Chang3.  Unzip Tink\_framework.zip into your Xcode project folder.
115*e7b1675dSTing-Kang Chang
116*e7b1675dSTing-Kang Chang    ```sh
117*e7b1675dSTing-Kang Chang    unzip bazel-bin/objc/Tink_framework.zip -d /path/to/your/project/folder/
118*e7b1675dSTing-Kang Chang    ```
119*e7b1675dSTing-Kang Chang
120*e7b1675dSTing-Kang Chang4.  Add the static framework to your Xcode project options:
121*e7b1675dSTing-Kang Chang
122*e7b1675dSTing-Kang Chang    *   Open your Xcode project
123*e7b1675dSTing-Kang Chang
124*e7b1675dSTing-Kang Chang    *   Navigate to your project's folder and drag Tink.framework into your
125*e7b1675dSTing-Kang Chang        Xcode's left pane.
126*e7b1675dSTing-Kang Chang
127*e7b1675dSTing-Kang Chang    *   In the following dialog select `Copy items if needed` and the target of
128*e7b1675dSTing-Kang Chang        your application that will use Tink. Click `Finish`.
129*e7b1675dSTing-Kang Chang
130*e7b1675dSTing-Kang Chang    *   Select your project on the left pane and click on "Build Settings"
131*e7b1675dSTing-Kang Chang
132*e7b1675dSTing-Kang Chang    *   Find `Other Linker Flags` and add `-lc++`
133*e7b1675dSTing-Kang Chang
134*e7b1675dSTing-Kang Chang5.  Start using Tink in your code.
135*e7b1675dSTing-Kang Chang
136*e7b1675dSTing-Kang Chang   You can import the umbrella header:
137*e7b1675dSTing-Kang Chang
138*e7b1675dSTing-Kang Chang   ```objc
139*e7b1675dSTing-Kang Chang   #import "Tink/Tink.h"
140*e7b1675dSTing-Kang Chang   ```
141*e7b1675dSTing-Kang Chang
142*e7b1675dSTing-Kang Chang   Or individual headers:
143*e7b1675dSTing-Kang Chang
144*e7b1675dSTing-Kang Chang   ```objc
145*e7b1675dSTing-Kang Chang   #import "Tink/TINKAeadConfig.h"
146*e7b1675dSTing-Kang Chang   #import "Tink/TINKAeadKeyTemplate.h"
147*e7b1675dSTing-Kang Chang   #import "Tink/TINKAead.h"
148*e7b1675dSTing-Kang Chang   ```
149*e7b1675dSTing-Kang Chang
150*e7b1675dSTing-Kang Chang## Initializing Tink
151*e7b1675dSTing-Kang Chang
152*e7b1675dSTing-Kang ChangTink provides customizable initialization, which allows for choosing specific
153*e7b1675dSTing-Kang Changimplementations (identified by _key types_) of desired primitives. This
154*e7b1675dSTing-Kang Changinitialization happens via _registration_ of the implementations.
155*e7b1675dSTing-Kang Chang
156*e7b1675dSTing-Kang ChangFor example, if you want to use all implementations of all primitives in the
157*e7b1675dSTing-Kang Changcurrent version of Tink, the initialization would look as follows:
158*e7b1675dSTing-Kang Chang
159*e7b1675dSTing-Kang Chang```objc
160*e7b1675dSTing-Kang Chang   #import "Tink/TINKAllConfig.h"
161*e7b1675dSTing-Kang Chang   #import "Tink/TINKConfig.h"
162*e7b1675dSTing-Kang Chang
163*e7b1675dSTing-Kang Chang   NSError *error = nil;
164*e7b1675dSTing-Kang Chang   TINKAllConfig *config = [[TINKAllConfig alloc] initWithError:&error];
165*e7b1675dSTing-Kang Chang   if (!config || error) {
166*e7b1675dSTing-Kang Chang     // handle error.
167*e7b1675dSTing-Kang Chang   }
168*e7b1675dSTing-Kang Chang
169*e7b1675dSTing-Kang Chang   if (![TINKConfig registerConfig:config error:&error]) {
170*e7b1675dSTing-Kang Chang     // handle error.
171*e7b1675dSTing-Kang Chang   }
172*e7b1675dSTing-Kang Chang```
173*e7b1675dSTing-Kang Chang
174*e7b1675dSTing-Kang ChangTo use only implementations of the AEAD primitive:
175*e7b1675dSTing-Kang Chang
176*e7b1675dSTing-Kang Chang```objc
177*e7b1675dSTing-Kang Chang    #import "Tink/TINKAeadConfig.h"
178*e7b1675dSTing-Kang Chang    #import "Tink/TINKConfig.h"
179*e7b1675dSTing-Kang Chang
180*e7b1675dSTing-Kang Chang    NSError *error = nil;
181*e7b1675dSTing-Kang Chang    TINKAeadConfig *aeadConfig = [[TINKAeadConfig alloc] initWithError:&error];
182*e7b1675dSTing-Kang Chang    if (!aeadConfig || error) {
183*e7b1675dSTing-Kang Chang      // handle error.
184*e7b1675dSTing-Kang Chang    }
185*e7b1675dSTing-Kang Chang
186*e7b1675dSTing-Kang Chang    if (![TINKConfig registerConfig:aeadConfig error:&error]) {
187*e7b1675dSTing-Kang Chang      // handle error.
188*e7b1675dSTing-Kang Chang    }
189*e7b1675dSTing-Kang Chang```
190*e7b1675dSTing-Kang Chang
191*e7b1675dSTing-Kang Chang## Generating new keys and keysets
192*e7b1675dSTing-Kang Chang
193*e7b1675dSTing-Kang ChangTo avoid accidental leakage of sensitive key material, you should avoid mixing
194*e7b1675dSTing-Kang Changkeyset generation and usage in code. To support the separation between these
195*e7b1675dSTing-Kang Changactivities the Tink package provides a command-line tool called
196*e7b1675dSTing-Kang Chang[Tinkey](TINKEY.md), which can be used for common key management tasks.
197*e7b1675dSTing-Kang Chang
198*e7b1675dSTing-Kang ChangStill, if there is a need to generate a KeysetHandle with fresh key material
199*e7b1675dSTing-Kang Changdirectly in Obj-C code, one can use
200*e7b1675dSTing-Kang Chang[`TINKKeysetHandle`](https://github.com/google/tink/blob/master/objc/TINKKeysetHandle.h)
201*e7b1675dSTing-Kang Changwith one of the available KeyTemplates (AeadKeyTemplate, HybridKeyTemplate, etc.):
202*e7b1675dSTing-Kang Chang
203*e7b1675dSTing-Kang Chang```objc
204*e7b1675dSTing-Kang Chang    #import "Tink/TINKAeadKeyTemplate.h"
205*e7b1675dSTing-Kang Chang    #import "Tink/TINKKeysetHandle.h"
206*e7b1675dSTing-Kang Chang
207*e7b1675dSTing-Kang Chang    NSError *error = nil;
208*e7b1675dSTing-Kang Chang    TINKAeadKeyTemplate *tpl = [[TINKAeadKeyTemplate alloc] initWithKeyTemplate:TINKAes128Gcm error:&error];
209*e7b1675dSTing-Kang Chang    if (!tpl || error) {
210*e7b1675dSTing-Kang Chang      // handle error.
211*e7b1675dSTing-Kang Chang    }
212*e7b1675dSTing-Kang Chang
213*e7b1675dSTing-Kang Chang    TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initWithKeyTemplate:tpl error:&error];
214*e7b1675dSTing-Kang Chang    if (!handle || error) {
215*e7b1675dSTing-Kang Chang      // handle error.
216*e7b1675dSTing-Kang Chang    }
217*e7b1675dSTing-Kang Chang```
218*e7b1675dSTing-Kang Chang
219*e7b1675dSTing-Kang Chang## Storing keysets
220*e7b1675dSTing-Kang Chang
221*e7b1675dSTing-Kang ChangAfter generating key material, you might want to persist it to a storage system.
222*e7b1675dSTing-Kang ChangTink supports storing keysets to the iOS keychain where they remain encrypted:
223*e7b1675dSTing-Kang Chang
224*e7b1675dSTing-Kang Chang```objc
225*e7b1675dSTing-Kang Chang    #import "Tink/TINKKeysetHandle.h"
226*e7b1675dSTing-Kang Chang
227*e7b1675dSTing-Kang Chang    NSError *error = nil;
228*e7b1675dSTing-Kang Chang    TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initWithKeyTemplate:tpl error:&error];
229*e7b1675dSTing-Kang Chang    if (!handle || error) {
230*e7b1675dSTing-Kang Chang      // handle error.
231*e7b1675dSTing-Kang Chang    }
232*e7b1675dSTing-Kang Chang
233*e7b1675dSTing-Kang Chang    NSString *keysetName = @"com.yourcompany.yourapp.uniqueKeysetName";
234*e7b1675dSTing-Kang Chang    if (![handle writeToKeychainWithName:keysetName overwrite:NO error:&error]) {
235*e7b1675dSTing-Kang Chang      // handle error.
236*e7b1675dSTing-Kang Chang    }
237*e7b1675dSTing-Kang Chang```
238*e7b1675dSTing-Kang Chang
239*e7b1675dSTing-Kang ChangThe keysets are stored in the keychain with the following options set:
240*e7b1675dSTing-Kang Chang
241*e7b1675dSTing-Kang Chang*   kSecAttrAccessible = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
242*e7b1675dSTing-Kang Chang*   kSecAttrSynchronizable = False
243*e7b1675dSTing-Kang Chang
244*e7b1675dSTing-Kang ChangThese settings prevent the keysets from leaving the device and keep them
245*e7b1675dSTing-Kang Changencrypted until the device is unlocked once.
246*e7b1675dSTing-Kang Chang
247*e7b1675dSTing-Kang Chang## Loading existing keysets
248*e7b1675dSTing-Kang Chang
249*e7b1675dSTing-Kang ChangTo load keysets from the iOS keychain:
250*e7b1675dSTing-Kang Chang
251*e7b1675dSTing-Kang Chang```objc
252*e7b1675dSTing-Kang Chang    #import "Tink/TINKKeysetHandle.h"
253*e7b1675dSTing-Kang Chang
254*e7b1675dSTing-Kang Chang    NSError *error = nil;
255*e7b1675dSTing-Kang Chang    NSString *keysetName = @"com.yourcompany.yourapp.uniqueKeysetName";
256*e7b1675dSTing-Kang Chang    TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initFromKeychainWithName:keysetName error:&error];
257*e7b1675dSTing-Kang Chang    if (!handle || error) {
258*e7b1675dSTing-Kang Chang      // handle error.
259*e7b1675dSTing-Kang Chang    }
260*e7b1675dSTing-Kang Chang```
261*e7b1675dSTing-Kang Chang
262*e7b1675dSTing-Kang ChangTo load cleartext keysets, use
263*e7b1675dSTing-Kang Chang[`TINKKeysetHandle+Cleartext`](https://github.com/google/tink/blob/master/objc/TINKKeysetHandle+Cleartext.h)
264*e7b1675dSTing-Kang Changand an appropriate
265*e7b1675dSTing-Kang Chang[`KeysetReader`](https://github.com/google/tink/blob/master/objc/TINKKeysetReader.h),
266*e7b1675dSTing-Kang Changdepending on the wire format of the stored keyset, for example a
267*e7b1675dSTing-Kang Chang[`TINKBinaryKeysetReader`](https://github.com/google/tink/blob/master/objc/TINKBinaryKeysetReader.h).
268*e7b1675dSTing-Kang Chang
269*e7b1675dSTing-Kang ChangNote: We don't recommend storing keysets in cleartext in the filesystem.
270*e7b1675dSTing-Kang ChangInstead, use the iOS keychain as demonstrated above.
271*e7b1675dSTing-Kang Chang
272*e7b1675dSTing-Kang Chang```objc
273*e7b1675dSTing-Kang Chang    #import "Tink/TINKBinaryKeysetReader.h"
274*e7b1675dSTing-Kang Chang    #import "Tink/TINKKeysetHandle+Cleartext.h"
275*e7b1675dSTing-Kang Chang
276*e7b1675dSTing-Kang Chang    NSError *error = nil;
277*e7b1675dSTing-Kang Chang    NSData *binaryKeyset = ...;
278*e7b1675dSTing-Kang Chang    TINKBinaryKeysetReader *reader = [[TINKBinaryKeysetReader alloc] initWithSerializedKeyset:binaryKeyset
279*e7b1675dSTing-Kang Chang                                                                                        error:&error];
280*e7b1675dSTing-Kang Chang    if (!reader || error) {
281*e7b1675dSTing-Kang Chang      // handle error.
282*e7b1675dSTing-Kang Chang    }
283*e7b1675dSTing-Kang Chang
284*e7b1675dSTing-Kang Chang    TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initCleartextKeysetHandleWithKeysetReader:reader
285*e7b1675dSTing-Kang Chang                                                                                             error:&error];
286*e7b1675dSTing-Kang Chang    if (!handle || error) {
287*e7b1675dSTing-Kang Chang      // handle error.
288*e7b1675dSTing-Kang Chang    }
289*e7b1675dSTing-Kang Chang```
290*e7b1675dSTing-Kang Chang
291*e7b1675dSTing-Kang Chang## Obtaining and using primitives
292*e7b1675dSTing-Kang Chang
293*e7b1675dSTing-Kang Chang[_Primitives_](PRIMITIVES.md) represent cryptographic operations offered by
294*e7b1675dSTing-Kang ChangTink, hence they form the core of Tink API. A primitive is just an interface
295*e7b1675dSTing-Kang Changthat specifies what operations are offered by the primitive. A primitive can
296*e7b1675dSTing-Kang Changhave multiple implementations, and you choose a desired implementation by using
297*e7b1675dSTing-Kang Changa key of corresponding type (see the [this
298*e7b1675dSTing-Kang Changsection](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for details).  A list of
299*e7b1675dSTing-Kang Changprimitives and their implementations currently supported by Tink in Objective-C
300*e7b1675dSTing-Kang Changcan be found [here](PRIMITIVES.md#objective-c).
301*e7b1675dSTing-Kang Chang
302*e7b1675dSTing-Kang ChangYou access implementations of a primitive via a factory that corresponds to the
303*e7b1675dSTing-Kang Changprimitive which offers corresponding `primitiveWithKeysetHandle:error:` methods.
304*e7b1675dSTing-Kang Chang
305*e7b1675dSTing-Kang Chang*  AEAD via `TINKAeadFactory`
306*e7b1675dSTing-Kang Chang*  MAC via `TINKMacFactory`
307*e7b1675dSTing-Kang Chang*  etc.
308*e7b1675dSTing-Kang Chang
309*e7b1675dSTing-Kang Chang### Symmetric key encryption
310*e7b1675dSTing-Kang Chang
311*e7b1675dSTing-Kang ChangYou can use an [AEAD (Authenticated Encryption with Associated
312*e7b1675dSTing-Kang ChangData)](PRIMITIVES.md#authenticated-encryption-with-associated-data) primitive to
313*e7b1675dSTing-Kang Changencrypt or decrypt data:
314*e7b1675dSTing-Kang Chang
315*e7b1675dSTing-Kang Chang```objc
316*e7b1675dSTing-Kang Chang    #import "Tink/TINKAead.h"
317*e7b1675dSTing-Kang Chang    #import "Tink/TINKKeysetHandle.h"
318*e7b1675dSTing-Kang Chang    #import "Tink/TINKAeadFactory.h"
319*e7b1675dSTing-Kang Chang
320*e7b1675dSTing-Kang Chang    // 1. Get a handle to the key material.
321*e7b1675dSTing-Kang Chang    TINKKeysetHandle *keysetHandle = ...;
322*e7b1675dSTing-Kang Chang
323*e7b1675dSTing-Kang Chang    // 2. Get the primitive.
324*e7b1675dSTing-Kang Chang    NSError *error = nil;
325*e7b1675dSTing-Kang Chang    id<TINKAead> aead = [TINKAeadFactory primitiveWithKeysetHandle:keysetHandle error:&error];
326*e7b1675dSTing-Kang Chang    if (!aead || error) {
327*e7b1675dSTing-Kang Chang      // handle error.
328*e7b1675dSTing-Kang Chang    }
329*e7b1675dSTing-Kang Chang
330*e7b1675dSTing-Kang Chang    // 3. Use the primitive.
331*e7b1675dSTing-Kang Chang    NSData *ciphertext = [aead encrypt:plaintext withAdditionalData:aad error:&error];
332*e7b1675dSTing-Kang Chang    if (!ciphertext || error) {
333*e7b1675dSTing-Kang Chang      // handle error.
334*e7b1675dSTing-Kang Chang    }
335*e7b1675dSTing-Kang Chang```
336*e7b1675dSTing-Kang Chang
337*e7b1675dSTing-Kang Chang### Hybrid encryption
338*e7b1675dSTing-Kang Chang
339*e7b1675dSTing-Kang ChangTo decrypt using [a combination of public key encryption and symmetric key
340*e7b1675dSTing-Kang Changencryption](PRIMITIVES.md#hybrid-encryption):
341*e7b1675dSTing-Kang Chang
342*e7b1675dSTing-Kang Chang```objc
343*e7b1675dSTing-Kang Chang    #import "Tink/TINKHybridDecrypt.h"
344*e7b1675dSTing-Kang Chang    #import "Tink/TINKKeysetHandle.h"
345*e7b1675dSTing-Kang Chang    #import "Tink/TINKHybridDecryptFactory.h"
346*e7b1675dSTing-Kang Chang
347*e7b1675dSTing-Kang Chang    // 1. Get a handle to the key material.
348*e7b1675dSTing-Kang Chang    TINKKeysetHandle *keysetHandle = ...;
349*e7b1675dSTing-Kang Chang
350*e7b1675dSTing-Kang Chang    // 2. Get the primitive.
351*e7b1675dSTing-Kang Chang    NSError *error = nil;
352*e7b1675dSTing-Kang Chang    id<TINKHybridDecrypt> hybridDecrypt = [TINKHybridDecryptFactory primitiveWithKeysetHandle:keysetHandle
353*e7b1675dSTing-Kang Chang                                                                                        error:&error];
354*e7b1675dSTing-Kang Chang    if (!hybridDecrypt || error) {
355*e7b1675dSTing-Kang Chang      // handle error.
356*e7b1675dSTing-Kang Chang    }
357*e7b1675dSTing-Kang Chang
358*e7b1675dSTing-Kang Chang    // 3. Use the primitive.
359*e7b1675dSTing-Kang Chang    NSData *plaintext = [hybridDecrypt decrypt:ciphertext withContextInfo:contextInfo error:&error];
360*e7b1675dSTing-Kang Chang    if (!plaintext || error) {
361*e7b1675dSTing-Kang Chang      // handle error.
362*e7b1675dSTing-Kang Chang    }
363*e7b1675dSTing-Kang Chang```
364