1# Tink for Java HOW-TO 2 3This document contains instructions and Java code snippets for common tasks in 4[Tink](https://github.com/tink-crypto/tink-java). 5 6If you want to contribute code to the Java implementation, please read the [Java 7hacking guide](JAVA-HACKING.md). 8 9## Setup instructions 10 11See https://developers.google.com/tink/tink-setup#java for setup 12instructions. 13 14## API documentation 15 16* Java: 17 * [1.9.0](https://google.github.io/tink/javadoc/tink/1.9.0) 18 * [HEAD-SNAPSHOT](https://google.github.io/tink/javadoc/tink/HEAD-SNAPSHOT) 19* Android: 20 * [1.9.0](https://google.github.io/tink/javadoc/tink-android/1.9.0) 21 * [HEAD-SNAPSHOT](https://google.github.io/tink/javadoc/tink-android/HEAD-SNAPSHOT) 22 23## Important warnings 24 25**Do not use APIs which have fields or methods marked with the `@Alpha` 26annotation.** They can be modified in any way, or even removed, at any time. 27They are in the package, but not for official, production release, but only for 28testing. 29 30**Do not use APIs in `com.google.crypto.tink.subtle`.** While they're generally 31safe to use, they're not meant for public consumption and can be modified in any 32way, or even removed, at any time. 33 34## Initializing Tink 35 36Tink provides customizable initialization, which allows you to choose specific 37implementations (identified by _key types_) of desired primitives. This 38initialization happens via _registration_ of the implementations. 39 40For example, if you want to use all implementations of all primitives in Tink, 41the initialization would be: 42 43```java 44 import com.google.crypto.tink.config.TinkConfig; 45 46 TinkConfig.register(); 47``` 48 49To use only implementations of the AEAD primitive: 50 51```java 52 import com.google.crypto.tink.aead.AeadConfig; 53 54 AeadConfig.register(); 55``` 56 57For custom initialization the registration proceeds directly via the 58`Registry` class: 59 60```java 61 import com.google.crypto.tink.Registry; 62 import my.custom.package.aead.MyAeadKeyManager; 63 64 // Register a custom implementation of AEAD. 65 Registry.registerKeyManager(new MyAeadKeyManager()); 66 67``` 68 69## Generating new keys and keysets 70 71Each `KeyManager`-implementation provides `newKey(..)`-methods that generate new 72keys of the corresponding key type. However, to avoid accidental leakage of 73sensitive key material, you should avoid mixing key(set) generation with 74key(set) usage in code. To support the separation between these activities, Tink 75provides a command-line tool called [Tinkey](TINKEY.md), which can be used for 76common key management tasks. 77 78Still, if there is a need to generate a KeysetHandle with fresh key material 79directly in Java code, you can use 80[`KeysetHandle`](https://github.com/tink-crypto/tink-java/blob/main/src/main/java/com/google/crypto/tink/KeysetHandle.java). 81For example, you can generate a keyset containing a randomly generated 82AES128-GCM key as follows. 83 84```java 85 import com.google.crypto.tink.KeysetHandle; 86 import com.google.crypto.tink.aead.PredefinedAeadParameters; 87 88 KeysetHandle keysetHandle = KeysetHandle.generateNew( 89 PredefinedAeadParameters.AES128_GCM); 90``` 91 92## Serializing keysets 93 94After generating key material, you might want to serialize it in order to 95persist it to a storage system, e.g., writing to a file. 96 97```java 98 import com.google.crypto.tink.InsecureSecretKeyAccess; 99 import com.google.crypto.tink.KeysetHandle; 100 import com.google.crypto.tink.TinkJsonProtoKeysetFormat; 101 import com.google.crypto.tink.aead.PredefinedAeadParameters; 102 import java.nio.Files; 103 104 // Generate the key material... 105 KeysetHandle keysetHandle = KeysetHandle.generateNew( 106 PredefinedAeadParameters.AES128_GCM); 107 108 // and serialize it to a string. 109 String keysetFilename = "my_keyset.json"; 110 String serializedKeyset = 111 TinkJsonProtoKeysetFormat.serializeKeyset(handle, InsecureSecretKeyAccess.get()); 112``` 113 114Parsing can be done with `TinkJsonProtoKeysetFormat.parseKeyset`. If the keyset 115has no secret key material, the method `serializeKeysetWithoutSecret` can be 116used (which does not require `InsecureSecretKeyAccess`). 117 118Storing keysets unencrypted on disk is not recommended. Tink supports encrypting 119keysets with master keys stored in remote key management systems, see for 120example 121https://developers.google.com/tink/client-side-encryption#java. 122 123## Obtaining and using primitives 124 125[Primitives](PRIMITIVES.md) represent cryptographic operations offered by Tink, 126hence they form the core of the Tink API. A primitive is an interface which 127specifies what operations are offered by the primitive. A primitive can have 128multiple implementations, and you choose a desired implementation by using a key 129of a corresponding type (see [this 130document](KEY-MANAGEMENT.md#key-keyset-and-keysethandle) for further details). 131 132A list of primitives and the implementations currently supported by Tink in Java 133can be found [here](PRIMITIVES.md#java). 134 135You obtain a primitive by calling the method `getPrimitive(classObject)` of a 136`KeysetHandle`, where the `classObject` is the class object corresponding to the 137primitive (for example `Aead.class` for AEAD). 138 139### Symmetric Key Encryption 140 141You can obtain and use an 142[AEAD](PRIMITIVES.md#authenticated-encryption-with-associated-data) 143(Authenticated Encryption with Associated Data) primitive to encrypt or decrypt 144data: 145 146```java 147 import com.google.crypto.tink.Aead; 148 import com.google.crypto.tink.aead.PredefinedAeadParameters; 149 150 // 1. Generate the key material. 151 KeysetHandle keysetHandle = KeysetHandle.generateNew( 152 PredefinedAeadParameters.AES128_GCM); 153 154 // 2. Get the primitive. 155 Aead aead = keysetHandle.getPrimitive(Aead.class); 156 157 // 3. Use the primitive to encrypt a plaintext, 158 byte[] ciphertext = aead.encrypt(plaintext, aad); 159 160 // ... or to decrypt a ciphertext. 161 byte[] decrypted = aead.decrypt(ciphertext, aad); 162``` 163 164### Deterministic symmetric key encryption 165 166You can obtain and use a 167[DeterministicAEAD](PRIMITIVES.md#deterministic-authenticated-encryption-with-associated-data) 168(Deterministic Authenticated Encryption with Associated Data primitive to 169encrypt or decrypt data: 170 171```java 172 import com.google.crypto.tink.daead.PredefinedDeterministicAeadParameters; 173 import com.google.crypto.tink.KeysetHandle; 174 175 // 1. Generate the key material. 176 KeysetHandle keysetHandle = KeysetHandle.generateNew( 177 PredefinedDeterministicAeadParameters.AES256_SIV); 178 179 // 2. Get the primitive. 180 DeterministicAead daead = 181 keysetHandle.getPrimitive(DeterministicAead.class); 182 183 // 3. Use the primitive to deterministically encrypt a plaintext, 184 byte[] ciphertext = daead.encryptDeterministically(plaintext, aad); 185 186 // ... or to deterministically decrypt a ciphertext. 187 byte[] decrypted = daead.decryptDeterministically(ciphertext, aad); 188``` 189 190### Symmetric key encryption of streaming data 191 192See 193https://developers.google.com/tink/encrypt-large-files-or-data-streams#java 194 195### Message Authentication Code 196 197See 198https://developers.google.com/tink/protect-data-from-tampering#java 199 200### Digital signatures 201 202See https://developers.google.com/tink/digitally-sign-data 203 204### Hybrid encryption 205 206See https://developers.google.com/tink/exchange-data#java 207 208### Envelope encryption 209 210Via the AEAD interface, Tink supports 211[envelope encryption](KEY-MANAGEMENT.md#envelope-encryption). 212 213For example, you can perform envelope encryption with a Google Cloud KMS key at 214`gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar` 215using the credentials in `credentials.json` as follows: 216 217```java 218 import com.google.crypto.tink.Aead; 219 import com.google.crypto.tink.KeyTemplates; 220 import com.google.crypto.tink.KeysetHandle; 221 import com.google.crypto.tink.KmsClients; 222 import com.google.crypto.tink.aead.KmsEnvelopeAeadKeyManager; 223 import com.google.crypto.tink.integration.gcpkms.GcpKmsClient; 224 225 // 1. Generate the key material. 226 String kmsKeyUri = 227 "gcp-kms://projects/tink-examples/locations/global/keyRings/foo/cryptoKeys/bar"; 228 KeysetHandle handle = 229 KeysetHandle.generateNew( 230 KmsEnvelopeAeadKeyManager.createKeyTemplate( 231 kmsKeyUri, KeyTemplates.get("AES128_GCM"))); 232 233 // 2. Register the KMS client. 234 KmsClients.add(new GcpKmsClient() 235 .withCredentials("credentials.json")); 236 237 // 3. Get the primitive. 238 Aead aead = handle.getPrimitive(Aead.class); 239 240 // 4. Use the primitive. 241 byte[] ciphertext = aead.encrypt(plaintext, aad); 242``` 243 244## Key rotation 245 246Support for key rotation in Tink is provided via the 247[`KeysetHandle.Builder`](https://github.com/tink-crypto/tink-java/blob/main/src/main/java/com/google/crypto/tink/KeysetHandle.java) 248class. 249 250You have to provide a `KeysetHandle`-object that contains the keyset that should 251be rotated, and a specification of the new key via a 252[`Parameters`](https://github.com/tink-crypto/tink-java/blob/main/src/main/java/com/google/crypto/tink/Parameters.java) 253object. 254 255```java 256 import com.google.crypto.tink.KeysetHandle; 257 import com.google.crypto.tink.KeysetManager; 258 259 KeysetHandle keysetHandle = ...; // existing keyset 260 KeysetHandle.Builder builder = KeysetHandle.newBuilder(keysetHandle); 261 builder.addEntry(KeysetHandle.generateEntryFromParameters( 262 ChaCha20Poly1305Parameters.create()).withRandomId()); 263 KeysetHandle keysetHandleWithAdditionalEntry = builder.build(); 264``` 265 266After a successful rotation, the resulting keyset contains a new key generated 267according to the specification in the parameters object. For the rotation to 268succeed the `Registry` must contain a key manager for the key type specified in 269`keyTemplate`. 270 271Alternatively, you can use [Tinkey](TINKEY.md) to rotate or manage a keyset. 272 273## Custom implementation of a primitive 274 275**NOTE**: The usage of **custom key managers should be enjoyed responsibly**. We 276(i.e. Tink developers) have no way of checking or enforcing that a custom 277implementation satisfies security properties of the corresponding primitive 278interface, so it is up to the implementer and the user of the custom 279implementation ensure the required properties are met. 280 281The main cryptographic operations offered by Tink are accessible via so-called 282_primitives_, which are interfaces that represent corresponding cryptographic 283functionalities. While Tink comes with several standard implementations of 284common primitives, it also allows for adding custom implementations of 285primitives. Such implementations allow for seamless integration of Tink with 286custom third-party cryptographic schemes or hardware modules, and in combination 287with [key rotation](#key-rotation) features, enables the painless migration 288between cryptographic schemes. 289 290To create a custom implementation of a primitive proceed as follows: 291 2921. Determine for which _primitive_ a custom implementation is needed. 2932. Define protocol buffers that hold key material and parameters for the custom 294 cryptographic scheme; the name of the key protocol buffer (a.k.a. type URL) 295 determines the _key type_ for the custom implementation. 2963. Implement a 297 [`KeyManager`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/KeyManager.java) 298 interface for the _primitive_ from step #1 and the _key type_ from step #2. 299 300To use a custom implementation of a primitive in an application, register with 301the 302[`Registry`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/Registry.java) 303the custom `KeyManager` implementation (from step #3 above) for the custom key 304type (from step #2 above): 305 306```java 307 Registry.registerKeyManager(keyManager); 308``` 309 310Afterwards the implementation will be accessed automatically by the 311`keysetHandle.getPrimitive` corresponding to the primitive (when keys of the 312specific key type are in use). It can also be retrieved directly via 313`Registry.getKeyManager(keyType)`. 314 315When defining the protocol buffers for the key material and parameters (step #2 316above), you should provide definitions of three messages: 317 318 * `...Params`: parameters of an instantiation of the primitive, 319 needed when a key is being used. 320 * `...Key`: the actual key proto, contains the key material and the 321 corresponding `...Params` proto. 322 * `...KeyFormat`: parameters needed to generate a new key. 323 324Here are a few conventions/recommendations when defining these messages (see 325[tink.proto](https://github.com/google/tink/blob/master/proto/tink.proto) and 326definitions of [existing key 327types](https://github.com/google/tink/blob/master/proto/) for details): 328 329 * `...Key` should contain a version field (a monotonic counter, `uint32 version;`), 330 which identifies the version of implementation that can work with this key. 331 * `...Params` should be a field of `...Key`, as by definition `...Params` 332 contains parameters needed when the key is being used. 333 * `...Params` should be also a field of `...KeyFormat`, so that given `...KeyFormat` 334 one has all information it needs to generate a new `...Key` message. 335 336Alternatively, depending on the use case requirements, you can skip step #2 337entirely and re-use an existing protocol buffer messages for the key material. 338In such a case, you should not configure the Registry via the `Config`-class, but 339rather register the needed `KeyManager`-instances manually. 340 341For a concrete example, let's assume that we'd like a custom implementation of 342the 343[`Aead`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/Aead.java) 344primitive (step #1). We define then three protocol buffer messages (step #2): 345 346 * `MyCustomAeadParams`: holds parameters needed for the use of the key material. 347 * `MyCustomAeadKey`: holds the actual key material and parameters needed for its use. 348 * `MyCustomAeadKeyFormat`: holds parameters needed for generation of a new `MyCustomAeadKey`-key. 349 350```proto 351 syntax = "proto3"; 352 package mycompany.mypackage; 353 354 message MyCustomAeadParams { 355 uint32 iv_size = 1; // size of initialization vector in bytes 356 } 357 358 message MyCustomAeadKeyFormat { 359 MyCustomAeadParams params = 1; 360 uint32 key_size = 2; // key size in bytes 361 } 362 363 // key_type: type.googleapis.com/mycompany.mypackage.MyCustomAeadKey 364 message MyCustomAeadKey { 365 uint32 version = 1; 366 MyCustomAeadParams params = 2; 367 bytes key_value = 3; // the actual key material 368 } 369``` 370 371The corresponding _key type_ in Java is defined as 372 373```java 374 String keyType = "type.googleapis.com/mycompany.mypackage.MyCustomAeadKey";` 375``` 376 377and the corresponding _key manager_ implements (step #3) the interface 378[`KeyManager<Aead>`](https://github.com/google/tink/blob/master/java_src/src/main/java/com/google/crypto/tink/KeyManager.java) 379 380```java 381 class MyCustomAeadKeyManager implements KeyManager<Aead> { 382 // ... 383 } 384``` 385 386After registering `MyCustomAeadKeyManager` with the Registry, it will be used 387when you call `keysetHandle.getPrimitive(Aead.class)`. 388