blob: cbc157bd7fd28cb30d8c0074f40e4acd57d4ce69 [file] [log] [blame] [view]
Haris Andrianakisdfc76f82018-04-10 15:02:08 -07001# Tink for Obj-C HOW-TO
2
cklcf1b7862019-08-21 14:18:29 -07003This document contains instructions and Obj-C code snippets for common tasks in
4[Tink](https://github.com/google/tink).
Haris Andrianakisdfc76f82018-04-10 15:02:08 -07005
0xflotus5bcaf8b2020-04-30 17:08:14 +02006## Setup instructions
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -07007
8Tink is released as a [Cocoapod](https://cocoapods.org/). It can be installed by
cklcf1b7862019-08-21 14:18:29 -07009using the pod command as described below, which is the recommended way to use
10Tink.
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -070011
cklcf1b7862019-08-21 14:18:29 -070012We also provide step-by-step instructions on building and using Tink from
13source.
Haris Andrianakise3521ea2018-07-12 17:21:12 -070014
cklcf1b7862019-08-21 14:18:29 -070015#### Supported platforms
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -070016
17 * iOS 9.0 or newer
18 * Xcode 9.2 or newer
19
20### Installing via Cocoapods
21
221. Change into the directory that contains your Xcode project.
23
24 ```sh
25 cd /path/to/your/Xcode project/
26 ```
27
282. Initialize Cocoapods.
29
30 ```sh
31 pod init
32 ```
cklcf1b7862019-08-21 14:18:29 -070033
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -070034 This command creates a file called Podfile.
35
363. Edit the Podfile.
37
cklcf1b7862019-08-21 14:18:29 -070038 For the current stable release, add the following line:
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -070039
40 ```
41 pod 'Tink'
42 ```
43
cklcf1b7862019-08-21 14:18:29 -070044 For a particular version, use a line like the following instead:
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -070045
46 ```
Haris Andrianakisb3f143a2018-07-12 16:28:50 -070047 pod 'Tink', '1.2.0-rc2'
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -070048 ```
49
Haris Andrianakisb3f143a2018-07-12 16:28:50 -070050 Note: Replace 1.2.0-rc2 with the pre-release version you want to install.
Haris Andrianakis81cdb2a2018-07-10 14:36:08 -070051
524. Install the pod.
53
54 ```sh
55 $ pod install
56 ```
57
585. Open the newly generated .xcworkspace and start using Tink.
59
60 You can import the umbrella header:
61
62 ```objc
63 #import "Tink/Tink.h"
64 ```
65
66 Or individual headers:
67
68 ```objc
69 #import "Tink/TINKAeadConfig.h"
70 #import "Tink/TINKAeadKeyTemplate.h"
71 #import "Tink/TINKAead.h"
72 ```
73
cklcf1b7862019-08-21 14:18:29 -070074### Installing from source
Haris Andrianakise3521ea2018-07-12 17:21:12 -070075
76#### Prerequisites
77
78To install Tink from the source code, the following prerequisites must be
79installed:
80
81* [git](https://git-scm.com/) - to download the source of Tink
82* [Bazel](https://www.bazel.build) v0.15.0 or newer - to build Tink
83
84#### Step-by-step instructions
85
cklcf1b7862019-08-21 14:18:29 -0700861. Clone Tink from GitHub.
Haris Andrianakise3521ea2018-07-12 17:21:12 -070087
88 ```sh
89 git clone https://github.com/google/tink/
90 ```
91
cklcf1b7862019-08-21 14:18:29 -0700922. Build the library and generate a static iOS framework.
Haris Andrianakise3521ea2018-07-12 17:21:12 -070093
94 ```sh
95 cd tink
96 export XCODE_VERSION=9.2
97 export IOS_SDK=11.2
98 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 ```
100
101 Adjust the following options according to your build environment:
102
103 * Set `XCODE_VERSION` to the Xcode version you are using to build your
104 application.
105
106 * Set `IOS_SDK` to the version of the iOS SDK you are using in your
107 application.
108
109 * The option `ios_multi_cpus` is used to generate a fat library that
110 includes multiple architectures. Before submitting your application to
111 the App Store you should generate a framework that includes only the ARM
112 architectures and link it to your binary.
113
cklcf1b7862019-08-21 14:18:29 -07001143. Unzip Tink\_framework.zip into your Xcode project folder.
Haris Andrianakise3521ea2018-07-12 17:21:12 -0700115
116 ```sh
117 unzip bazel-bin/objc/Tink_framework.zip -d /path/to/your/project/folder/
118 ```
119
1204. Add the static framework to your Xcode project options:
121
122 * Open your Xcode project
123
124 * Navigate to your project's folder and drag Tink.framework into your
125 Xcode's left pane.
126
127 * In the following dialog select `Copy items if needed` and the target of
128 your application that will use Tink. Click `Finish`.
129
130 * Select your project on the left pane and click on "Build Settings"
131
132 * Find `Other Linker Flags` and add `-lc++`
133
cklcf1b7862019-08-21 14:18:29 -07001345. Start using Tink in your code.
Haris Andrianakise3521ea2018-07-12 17:21:12 -0700135
cklcf1b7862019-08-21 14:18:29 -0700136 You can import the umbrella header:
137
138 ```objc
139 #import "Tink/Tink.h"
140 ```
141
142 Or individual headers:
143
144 ```objc
145 #import "Tink/TINKAeadConfig.h"
146 #import "Tink/TINKAeadKeyTemplate.h"
147 #import "Tink/TINKAead.h"
148 ```
Haris Andrianakise3521ea2018-07-12 17:21:12 -0700149
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700150## Initializing Tink
151
152Tink provides customizable initialization, which allows for choosing specific
153implementations (identified by _key types_) of desired primitives. This
154initialization happens via _registration_ of the implementations.
155
Haris Andrianakis0ee8fee2018-07-12 11:10:39 -0700156For example, if you want to use all implementations of all primitives in the
157current version of Tink, the initialization would look as follows:
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700158
159```objc
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700160 #import "Tink/TINKAllConfig.h"
161 #import "Tink/TINKConfig.h"
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700162
163 NSError *error = nil;
Haris Andrianakis0ee8fee2018-07-12 11:10:39 -0700164 TINKAllConfig *config = [[TINKAllConfig alloc] initWithError:&error];
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700165 if (!config || error) {
166 // handle error.
167 }
168
169 if (![TINKConfig registerConfig:config error:&error]) {
170 // handle error.
171 }
172```
173
174To use only implementations of the AEAD primitive:
175
176```objc
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700177 #import "Tink/TINKAeadConfig.h"
178 #import "Tink/TINKConfig.h"
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700179
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700180 NSError *error = nil;
Haris Andrianakis0ee8fee2018-07-12 11:10:39 -0700181 TINKAeadConfig *aeadConfig = [[TINKAeadConfig alloc] initWithError:&error];
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700182 if (!aeadConfig || error) {
183 // handle error.
184 }
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700185
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700186 if (![TINKConfig registerConfig:aeadConfig error:&error]) {
187 // handle error.
188 }
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700189```
190
cklcf1b7862019-08-21 14:18:29 -0700191## Generating new keys and keysets
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700192
cklcf1b7862019-08-21 14:18:29 -0700193To avoid accidental leakage of sensitive key material, you should avoid mixing
194keyset generation and usage in code. To support the separation between these
195activities the Tink package provides a command-line tool called
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700196[Tinkey](TINKEY.md), which can be used for common key management tasks.
197
198Still, if there is a need to generate a KeysetHandle with fresh key material
199directly in Obj-C code, one can use
200[`TINKKeysetHandle`](https://github.com/google/tink/blob/master/objc/TINKKeysetHandle.h)
cklcf1b7862019-08-21 14:18:29 -0700201with one of the available KeyTemplates (AeadKeyTemplate, HybridKeyTemplate, etc.):
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700202
203```objc
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700204 #import "Tink/TINKAeadKeyTemplate.h"
205 #import "Tink/TINKKeysetHandle.h"
206
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700207 NSError *error = nil;
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700208 TINKAeadKeyTemplate *tpl = [[TINKAeadKeyTemplate alloc] initWithKeyTemplate:TINKAes128Gcm error:&error];
209 if (!tpl || error) {
210 // handle error.
211 }
212
213 TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initWithKeyTemplate:tpl error:&error];
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700214 if (!handle || error) {
215 // handle error.
216 }
217```
218
cklcf1b7862019-08-21 14:18:29 -0700219## Storing keysets
Haris Andrianakisfb7ed282018-07-11 15:12:53 -0700220
221After generating key material, you might want to persist it to a storage system.
222Tink supports storing keysets to the iOS keychain where they remain encrypted:
223
224```objc
225 #import "Tink/TINKKeysetHandle.h"
226
227 NSError *error = nil;
228 TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initWithKeyTemplate:tpl error:&error];
229 if (!handle || error) {
230 // handle error.
231 }
232
233 NSString *keysetName = @"com.yourcompany.yourapp.uniqueKeysetName";
234 if (![handle writeToKeychainWithName:keysetName overwrite:NO error:&error]) {
235 // handle error.
236 }
237```
238
239The keysets are stored in the keychain with the following options set:
240
241* kSecAttrAccessible = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
242* kSecAttrSynchronizable = False
243
244These settings prevent the keysets from leaving the device and keep them
245encrypted until the device is unlocked once.
246
cklcf1b7862019-08-21 14:18:29 -0700247## Loading existing keysets
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700248
Haris Andrianakisfb7ed282018-07-11 15:12:53 -0700249To load keysets from the iOS keychain:
250
251```objc
252 #import "Tink/TINKKeysetHandle.h"
253
254 NSError *error = nil;
255 NSString *keysetName = @"com.yourcompany.yourapp.uniqueKeysetName";
256 TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initFromKeychainWithName:keysetName error:&error];
257 if (!handle || error) {
258 // handle error.
259 }
260```
261
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700262To load cleartext keysets, use
263[`TINKKeysetHandle+Cleartext`](https://github.com/google/tink/blob/master/objc/TINKKeysetHandle+Cleartext.h)
264and an appropriate
265[`KeysetReader`](https://github.com/google/tink/blob/master/objc/TINKKeysetReader.h),
266depending on the wire format of the stored keyset, for example a
267[`TINKBinaryKeysetReader`](https://github.com/google/tink/blob/master/objc/TINKBinaryKeysetReader.h).
268
Haris Andrianakisfb7ed282018-07-11 15:12:53 -0700269Note: We don't recommend storing keysets in cleartext in the filesystem.
270Instead, use the iOS keychain as demonstrated above.
271
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700272```objc
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700273 #import "Tink/TINKBinaryKeysetReader.h"
274 #import "Tink/TINKKeysetHandle+Cleartext.h"
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700275
276 NSError *error = nil;
277 NSData *binaryKeyset = ...;
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700278 TINKBinaryKeysetReader *reader = [[TINKBinaryKeysetReader alloc] initWithSerializedKeyset:binaryKeyset
279 error:&error];
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700280 if (!reader || error) {
281 // handle error.
282 }
283
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700284 TINKKeysetHandle *handle = [[TINKKeysetHandle alloc] initCleartextKeysetHandleWithKeysetReader:reader
285 error:&error];
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700286 if (!handle || error) {
287 // handle error.
288 }
289```
290
cklcf1b7862019-08-21 14:18:29 -0700291## Obtaining and using primitives
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700292
293[_Primitives_](PRIMITIVES.md) represent cryptographic operations offered by
294Tink, hence they form the core of Tink API. A primitive is just an interface
295that specifies what operations are offered by the primitive. A primitive can
cklcf1b7862019-08-21 14:18:29 -0700296have multiple implementations, and you choose a desired implementation by using
297a key of corresponding type (see the [this
298section](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for details). A list of
0xflotus5bcaf8b2020-04-30 17:08:14 +0200299primitives and their implementations currently supported by Tink in Objective-C
cklcf1b7862019-08-21 14:18:29 -0700300can be found [here](PRIMITIVES.md#objective-c).
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700301
cklcf1b7862019-08-21 14:18:29 -0700302You access implementations of a primitive via a factory that corresponds to the
303primitive which offers corresponding `primitiveWithKeysetHandle:error:` methods.
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700304
cklcf1b7862019-08-21 14:18:29 -0700305* AEAD via `TINKAeadFactory`
306* MAC via `TINKMacFactory`
307* etc.
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700308
cklcf1b7862019-08-21 14:18:29 -0700309### Symmetric key encryption
310
311You can use an [AEAD (Authenticated Encryption with Associated
312Data)](PRIMITIVES.md#authenticated-encryption-with-associated-data) primitive to
313encrypt or decrypt data:
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700314
315```objc
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700316 #import "Tink/TINKAead.h"
317 #import "Tink/TINKKeysetHandle.h"
318 #import "Tink/TINKAeadFactory.h"
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700319
320 // 1. Get a handle to the key material.
321 TINKKeysetHandle *keysetHandle = ...;
322
323 // 2. Get the primitive.
324 NSError *error = nil;
325 id<TINKAead> aead = [TINKAeadFactory primitiveWithKeysetHandle:keysetHandle error:&error];
326 if (!aead || error) {
327 // handle error.
328 }
329
330 // 3. Use the primitive.
331 NSData *ciphertext = [aead encrypt:plaintext withAdditionalData:aad error:&error];
332 if (!ciphertext || error) {
333 // handle error.
334 }
335```
336
cklcf1b7862019-08-21 14:18:29 -0700337### Hybrid encryption
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700338
339To decrypt using [a combination of public key encryption and symmetric key
340encryption](PRIMITIVES.md#hybrid-encryption):
341
342```objc
Haris Andrianakis57c0a722018-07-03 10:33:56 -0700343 #import "Tink/TINKHybridDecrypt.h"
344 #import "Tink/TINKKeysetHandle.h"
345 #import "Tink/TINKHybridDecryptFactory.h"
Haris Andrianakisdfc76f82018-04-10 15:02:08 -0700346
347 // 1. Get a handle to the key material.
348 TINKKeysetHandle *keysetHandle = ...;
349
350 // 2. Get the primitive.
351 NSError *error = nil;
352 id<TINKHybridDecrypt> hybridDecrypt = [TINKHybridDecryptFactory primitiveWithKeysetHandle:keysetHandle
353 error:&error];
354 if (!hybridDecrypt || error) {
355 // handle error.
356 }
357
358 // 3. Use the primitive.
359 NSData *plaintext = [hybridDecrypt decrypt:ciphertext withContextInfo:contextInfo error:&error];
360 if (!plaintext || error) {
361 // handle error.
362 }
363```
OSZAR »