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