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