xref: /aosp_15_r20/external/tink/docs/JAVA-HOWTO.md (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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