• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 package com.google.crypto.tink.testing;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static java.nio.charset.StandardCharsets.UTF_8;
21 import static java.util.concurrent.TimeUnit.SECONDS;
22 import static org.junit.Assert.assertThrows;
23 
24 import com.google.crypto.tink.InsecureSecretKeyAccess;
25 import com.google.crypto.tink.KeyTemplate;
26 import com.google.crypto.tink.KeyTemplates;
27 import com.google.crypto.tink.KeysetHandle;
28 import com.google.crypto.tink.TinkProtoKeysetFormat;
29 import com.google.crypto.tink.config.TinkConfig;
30 import com.google.crypto.tink.daead.AesSivKeyManager;
31 import com.google.crypto.tink.internal.KeyTemplateProtoConverter;
32 import com.google.crypto.tink.mac.HmacKeyManager;
33 import com.google.crypto.tink.prf.HmacPrfKeyManager;
34 import com.google.crypto.tink.streamingaead.AesGcmHkdfStreamingKeyManager;
35 import com.google.crypto.tink.testing.proto.AeadDecryptRequest;
36 import com.google.crypto.tink.testing.proto.AeadDecryptResponse;
37 import com.google.crypto.tink.testing.proto.AeadEncryptRequest;
38 import com.google.crypto.tink.testing.proto.AeadEncryptResponse;
39 import com.google.crypto.tink.testing.proto.AeadGrpc;
40 import com.google.crypto.tink.testing.proto.AnnotatedKeyset;
41 import com.google.crypto.tink.testing.proto.BytesValue;
42 import com.google.crypto.tink.testing.proto.ComputeMacRequest;
43 import com.google.crypto.tink.testing.proto.ComputeMacResponse;
44 import com.google.crypto.tink.testing.proto.CreationRequest;
45 import com.google.crypto.tink.testing.proto.CreationResponse;
46 import com.google.crypto.tink.testing.proto.DeterministicAeadDecryptRequest;
47 import com.google.crypto.tink.testing.proto.DeterministicAeadDecryptResponse;
48 import com.google.crypto.tink.testing.proto.DeterministicAeadEncryptRequest;
49 import com.google.crypto.tink.testing.proto.DeterministicAeadEncryptResponse;
50 import com.google.crypto.tink.testing.proto.DeterministicAeadGrpc;
51 import com.google.crypto.tink.testing.proto.KeysetFromJsonRequest;
52 import com.google.crypto.tink.testing.proto.KeysetFromJsonResponse;
53 import com.google.crypto.tink.testing.proto.KeysetGenerateRequest;
54 import com.google.crypto.tink.testing.proto.KeysetGenerateResponse;
55 import com.google.crypto.tink.testing.proto.KeysetGrpc;
56 import com.google.crypto.tink.testing.proto.KeysetReadEncryptedRequest;
57 import com.google.crypto.tink.testing.proto.KeysetReadEncryptedResponse;
58 import com.google.crypto.tink.testing.proto.KeysetReaderType;
59 import com.google.crypto.tink.testing.proto.KeysetTemplateRequest;
60 import com.google.crypto.tink.testing.proto.KeysetTemplateResponse;
61 import com.google.crypto.tink.testing.proto.KeysetToJsonRequest;
62 import com.google.crypto.tink.testing.proto.KeysetToJsonResponse;
63 import com.google.crypto.tink.testing.proto.KeysetWriteEncryptedRequest;
64 import com.google.crypto.tink.testing.proto.KeysetWriteEncryptedResponse;
65 import com.google.crypto.tink.testing.proto.KeysetWriterType;
66 import com.google.crypto.tink.testing.proto.MacGrpc;
67 import com.google.crypto.tink.testing.proto.MetadataGrpc;
68 import com.google.crypto.tink.testing.proto.PrfSetComputeRequest;
69 import com.google.crypto.tink.testing.proto.PrfSetComputeResponse;
70 import com.google.crypto.tink.testing.proto.PrfSetGrpc;
71 import com.google.crypto.tink.testing.proto.PrfSetKeyIdsRequest;
72 import com.google.crypto.tink.testing.proto.PrfSetKeyIdsResponse;
73 import com.google.crypto.tink.testing.proto.ServerInfoRequest;
74 import com.google.crypto.tink.testing.proto.ServerInfoResponse;
75 import com.google.crypto.tink.testing.proto.StreamingAeadDecryptRequest;
76 import com.google.crypto.tink.testing.proto.StreamingAeadDecryptResponse;
77 import com.google.crypto.tink.testing.proto.StreamingAeadEncryptRequest;
78 import com.google.crypto.tink.testing.proto.StreamingAeadEncryptResponse;
79 import com.google.crypto.tink.testing.proto.StreamingAeadGrpc;
80 import com.google.crypto.tink.testing.proto.VerifyMacRequest;
81 import com.google.crypto.tink.testing.proto.VerifyMacResponse;
82 import com.google.protobuf.ByteString;
83 import io.grpc.ManagedChannel;
84 import io.grpc.Server;
85 import io.grpc.StatusRuntimeException;
86 import io.grpc.inprocess.InProcessChannelBuilder;
87 import io.grpc.inprocess.InProcessServerBuilder;
88 import java.util.Optional;
89 import org.junit.After;
90 import org.junit.Before;
91 import org.junit.Test;
92 import org.junit.runner.RunWith;
93 import org.junit.runners.JUnit4;
94 
95 @RunWith(JUnit4.class)
96 public final class TestingServicesTest {
97   private Server server;
98   private ManagedChannel channel;
99   MetadataGrpc.MetadataBlockingStub metadataStub;
100   KeysetGrpc.KeysetBlockingStub keysetStub;
101   AeadGrpc.AeadBlockingStub aeadStub;
102   DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub;
103   StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub;
104   MacGrpc.MacBlockingStub macStub;
105   PrfSetGrpc.PrfSetBlockingStub prfSetStub;
106 
107   @Before
setUp()108   public void setUp() throws Exception {
109     TinkConfig.register();
110     String serverName = InProcessServerBuilder.generateName();
111     server =
112         InProcessServerBuilder.forName(serverName)
113             .directExecutor()
114             .addService(new MetadataServiceImpl())
115             .addService(new KeysetServiceImpl())
116             .addService(new AeadServiceImpl())
117             .addService(new DeterministicAeadServiceImpl())
118             .addService(new StreamingAeadServiceImpl())
119             .addService(new MacServiceImpl())
120             .addService(new PrfSetServiceImpl())
121             .build()
122             .start();
123     channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
124     metadataStub = MetadataGrpc.newBlockingStub(channel);
125     keysetStub = KeysetGrpc.newBlockingStub(channel);
126     aeadStub = AeadGrpc.newBlockingStub(channel);
127     daeadStub = DeterministicAeadGrpc.newBlockingStub(channel);
128     streamingAeadStub = StreamingAeadGrpc.newBlockingStub(channel);
129     macStub = MacGrpc.newBlockingStub(channel);
130     prfSetStub = PrfSetGrpc.newBlockingStub(channel);
131   }
132 
133   @After
tearDown()134   public void tearDown() throws Exception {
135     assertThat(channel.shutdown().awaitTermination(5, SECONDS)).isTrue();
136     assertThat(server.shutdown().awaitTermination(5, SECONDS)).isTrue();
137   }
138 
generateKeyset( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] template)139   private static KeysetGenerateResponse generateKeyset(
140       KeysetGrpc.KeysetBlockingStub keysetStub, byte[] template) {
141     KeysetGenerateRequest genRequest =
142         KeysetGenerateRequest.newBuilder().setTemplate(ByteString.copyFrom(template)).build();
143     return keysetStub.generate(genRequest);
144   }
145 
keysetToJson( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] keyset)146   private static KeysetToJsonResponse keysetToJson(
147       KeysetGrpc.KeysetBlockingStub keysetStub, byte[] keyset) {
148     KeysetToJsonRequest request =
149         KeysetToJsonRequest.newBuilder().setKeyset(ByteString.copyFrom(keyset)).build();
150     return keysetStub.toJson(request);
151   }
152 
keysetFromJson( KeysetGrpc.KeysetBlockingStub keysetStub, String jsonKeyset)153   private static KeysetFromJsonResponse keysetFromJson(
154       KeysetGrpc.KeysetBlockingStub keysetStub, String jsonKeyset) {
155     KeysetFromJsonRequest request =
156         KeysetFromJsonRequest.newBuilder().setJsonKeyset(jsonKeyset).build();
157     return keysetStub.fromJson(request);
158   }
159 
160   @Test
template_success()161   public void template_success() throws Exception {
162     KeysetTemplateRequest request =
163         KeysetTemplateRequest.newBuilder().setTemplateName("AES256_GCM").build();
164     KeysetTemplateResponse response = keysetStub.getTemplate(request);
165     assertThat(response.getErr()).isEmpty();
166     KeyTemplate template =
167         KeyTemplateProtoConverter.fromByteArray(response.getKeyTemplate().toByteArray());
168     assertThat(template.toParameters()).isEqualTo(KeyTemplates.get("AES256_GCM").toParameters());
169   }
170 
171   @Test
template_not_found()172   public void template_not_found() throws Exception {
173     KeysetTemplateRequest request =
174         KeysetTemplateRequest.newBuilder().setTemplateName("UNKNOWN_TEMPLATE").build();
175     KeysetTemplateResponse response = keysetStub.getTemplate(request);
176     assertThat(response.getErr()).isNotEmpty();
177   }
178 
179   @Test
fromJson_success()180   public void fromJson_success() throws Exception {
181     String jsonKeyset =
182         ""
183             + "{"
184             + "  \"primaryKeyId\": 42,"
185             + "  \"key\": ["
186             + "    {"
187             + "      \"keyData\": {"
188             + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.AesGcmKey\","
189             + "        \"keyMaterialType\": \"SYMMETRIC\","
190             + "        \"value\": \"GhCC74uJ+2f4qlpaHwR4ylNQ\""
191             + "      },"
192             + "      \"outputPrefixType\": \"TINK\","
193             + "      \"keyId\": 42,"
194             + "      \"status\": \"ENABLED\""
195             + "    }"
196             + "  ]"
197             + "}";
198     KeysetFromJsonResponse fromResponse = keysetFromJson(keysetStub, jsonKeyset);
199     assertThat(fromResponse.getErr()).isEmpty();
200     byte[] serializedKeyset = fromResponse.getKeyset().toByteArray();
201 
202     KeysetHandle parseKeysetHandle =
203         TinkProtoKeysetFormat.parseKeyset(serializedKeyset, InsecureSecretKeyAccess.get());
204     assertThat(parseKeysetHandle.getPrimary().getId()).isEqualTo(42);
205   }
206 
207   @Test
toFromJson_success()208   public void toFromJson_success() throws Exception {
209     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
210 
211     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
212     assertThat(keysetResponse.getErr()).isEmpty();
213     byte[] keyset = keysetResponse.getKeyset().toByteArray();
214 
215     KeysetToJsonResponse toResponse = keysetToJson(keysetStub, keyset);
216     assertThat(toResponse.getErr()).isEmpty();
217     String jsonKeyset = toResponse.getJsonKeyset();
218 
219     KeysetFromJsonResponse fromResponse = keysetFromJson(keysetStub, jsonKeyset);
220     assertThat(fromResponse.getErr()).isEmpty();
221     byte[] output = fromResponse.getKeyset().toByteArray();
222 
223     assertThat(output).isEqualTo(keyset);
224   }
225 
keysetReadEncrypted( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] encryptedKeyset, byte[] masterKeyset, Optional<byte[]> associatedData)226   private static KeysetReadEncryptedResponse keysetReadEncrypted(
227       KeysetGrpc.KeysetBlockingStub keysetStub,
228       byte[] encryptedKeyset,
229       byte[] masterKeyset,
230       Optional<byte[]> associatedData) {
231     KeysetReadEncryptedRequest.Builder requestBuilder =
232         KeysetReadEncryptedRequest.newBuilder()
233             .setEncryptedKeyset(ByteString.copyFrom(encryptedKeyset))
234             .setMasterKeyset(ByteString.copyFrom(masterKeyset))
235             .setKeysetReaderType(KeysetReaderType.KEYSET_READER_BINARY);
236     if (associatedData.isPresent()) {
237       requestBuilder.setAssociatedData(
238           BytesValue.newBuilder().setValue(ByteString.copyFrom(associatedData.get())).build());
239     }
240     return keysetStub.readEncrypted(requestBuilder.build());
241   }
242 
keysetWriteEncrypted( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] keyset, byte[] masterKeyset, Optional<byte[]> associatedData)243   private static KeysetWriteEncryptedResponse keysetWriteEncrypted(
244       KeysetGrpc.KeysetBlockingStub keysetStub,
245       byte[] keyset,
246       byte[] masterKeyset,
247       Optional<byte[]> associatedData) {
248     KeysetWriteEncryptedRequest.Builder requestBuilder =
249         KeysetWriteEncryptedRequest.newBuilder()
250             .setKeyset(ByteString.copyFrom(keyset))
251             .setMasterKeyset(ByteString.copyFrom(masterKeyset))
252             .setKeysetWriterType(KeysetWriterType.KEYSET_WRITER_BINARY);
253     if (associatedData.isPresent()) {
254       requestBuilder.setAssociatedData(
255           BytesValue.newBuilder().setValue(ByteString.copyFrom(associatedData.get())).build());
256     }
257     return keysetStub.writeEncrypted(requestBuilder.build());
258   }
259 
260   @Test
generateEncryptDecryptKeyset()261   public void generateEncryptDecryptKeyset() throws Exception {
262     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
263 
264     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
265     assertThat(keysetResponse.getErr()).isEmpty();
266     byte[] keyset = keysetResponse.getKeyset().toByteArray();
267 
268     KeysetGenerateResponse masterKeysetResponse = generateKeyset(keysetStub, template);
269     assertThat(masterKeysetResponse.getErr()).isEmpty();
270     byte[] masterKeyset = masterKeysetResponse.getKeyset().toByteArray();
271 
272     KeysetWriteEncryptedResponse writeResponse =
273         keysetWriteEncrypted(
274             keysetStub, keyset, masterKeyset, /*associatedData=*/ Optional.empty());
275     assertThat(writeResponse.getErr()).isEmpty();
276     byte[] encryptedKeyset = writeResponse.getEncryptedKeyset().toByteArray();
277 
278     assertThat(encryptedKeyset).isNotEqualTo(keyset);
279 
280     KeysetReadEncryptedResponse readResponse =
281         keysetReadEncrypted(
282             keysetStub, encryptedKeyset, masterKeyset, /*associatedData=*/ Optional.empty());
283     assertThat(readResponse.getErr()).isEmpty();
284     byte[] output = readResponse.getKeyset().toByteArray();
285 
286     assertThat(output).isEqualTo(keyset);
287 
288     // Empty associated data should be the same as no associated data.
289     KeysetReadEncryptedResponse readResponseWithEmptyAssociatedData =
290         keysetReadEncrypted(
291             keysetStub,
292             encryptedKeyset,
293             masterKeyset,
294             /*associatedData=*/ Optional.of(new byte[0]));
295     assertThat(readResponseWithEmptyAssociatedData.getErr()).isEmpty();
296     assertThat(readResponseWithEmptyAssociatedData.getKeyset().toByteArray()).isEqualTo(keyset);
297 
298     KeysetReadEncryptedResponse readResponseWithInvalidAssociatedData =
299         keysetReadEncrypted(
300             keysetStub,
301             encryptedKeyset,
302             masterKeyset,
303             Optional.of("invalidAssociatedData".getBytes(UTF_8)));
304     assertThat(readResponseWithInvalidAssociatedData.getErr()).isNotEmpty();
305   }
306 
307   @Test
generateEncryptDecryptKeysetWithAssociatedData()308   public void generateEncryptDecryptKeysetWithAssociatedData() throws Exception {
309     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
310     byte[] associatedData = "a".getBytes(UTF_8);
311 
312     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
313     assertThat(keysetResponse.getErr()).isEmpty();
314     byte[] keyset = keysetResponse.getKeyset().toByteArray();
315 
316     KeysetGenerateResponse masterKeysetResponse = generateKeyset(keysetStub, template);
317     assertThat(masterKeysetResponse.getErr()).isEmpty();
318     byte[] masterKeyset = masterKeysetResponse.getKeyset().toByteArray();
319 
320     KeysetWriteEncryptedResponse writeResponse =
321         keysetWriteEncrypted(keysetStub, keyset, masterKeyset, Optional.of(associatedData));
322     assertThat(writeResponse.getErr()).isEmpty();
323     byte[] encryptedKeyset = writeResponse.getEncryptedKeyset().toByteArray();
324 
325     assertThat(encryptedKeyset).isNotEqualTo(keyset);
326 
327     KeysetReadEncryptedResponse readResponse =
328         keysetReadEncrypted(keysetStub, encryptedKeyset, masterKeyset, Optional.of(associatedData));
329     assertThat(readResponse.getErr()).isEmpty();
330     byte[] output = readResponse.getKeyset().toByteArray();
331 
332     assertThat(output).isEqualTo(keyset);
333 
334     KeysetReadEncryptedResponse readResponseWithInvalidAssociatedData =
335         keysetReadEncrypted(
336             keysetStub,
337             encryptedKeyset,
338             masterKeyset,
339             Optional.of("invalidAssociatedData".getBytes(UTF_8)));
340     assertThat(readResponseWithInvalidAssociatedData.getErr()).isNotEmpty();
341 
342     KeysetReadEncryptedResponse readResponseWithoutAssociatedData =
343         keysetReadEncrypted(
344             keysetStub, encryptedKeyset, masterKeyset, /*associatedData=*/ Optional.empty());
345     assertThat(readResponseWithoutAssociatedData.getErr()).isNotEmpty();
346   }
347 
348   @Test
generateEncryptDecryptKeysetWithEmptyAssociatedData()349   public void generateEncryptDecryptKeysetWithEmptyAssociatedData() throws Exception {
350     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
351     byte[] emptyAssociatedData = new byte[0];
352 
353     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
354     assertThat(keysetResponse.getErr()).isEmpty();
355     byte[] keyset = keysetResponse.getKeyset().toByteArray();
356 
357     KeysetGenerateResponse masterKeysetResponse = generateKeyset(keysetStub, template);
358     assertThat(masterKeysetResponse.getErr()).isEmpty();
359     byte[] masterKeyset = masterKeysetResponse.getKeyset().toByteArray();
360 
361     KeysetWriteEncryptedResponse writeResponse =
362         keysetWriteEncrypted(keysetStub, keyset, masterKeyset, Optional.of(emptyAssociatedData));
363     assertThat(writeResponse.getErr()).isEmpty();
364     byte[] encryptedKeyset = writeResponse.getEncryptedKeyset().toByteArray();
365 
366     assertThat(encryptedKeyset).isNotEqualTo(keyset);
367 
368     KeysetReadEncryptedResponse readResponse =
369         keysetReadEncrypted(
370             keysetStub, encryptedKeyset, masterKeyset, Optional.of(emptyAssociatedData));
371     assertThat(readResponse.getErr()).isEmpty();
372     byte[] output = readResponse.getKeyset().toByteArray();
373     assertThat(output).isEqualTo(keyset);
374 
375     KeysetReadEncryptedResponse readResponseWithoutAssociatedData =
376         keysetReadEncrypted(keysetStub, encryptedKeyset, masterKeyset, Optional.empty());
377     assertThat(readResponseWithoutAssociatedData.getErr()).isEmpty();
378     assertThat(readResponseWithoutAssociatedData.getKeyset().toByteArray()).isEqualTo(keyset);
379   }
380 
381   @Test
encryptDecryptInvalidKeyset_fails()382   public void encryptDecryptInvalidKeyset_fails() throws Exception {
383     byte[] invalidData = "invalid".getBytes(UTF_8);
384     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
385 
386     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
387     assertThat(keysetResponse.getErr()).isEmpty();
388     byte[] keyset = keysetResponse.getKeyset().toByteArray();
389 
390     KeysetGenerateResponse masterKeysetResponse = generateKeyset(keysetStub, template);
391     assertThat(masterKeysetResponse.getErr()).isEmpty();
392     byte[] masterKeyset = masterKeysetResponse.getKeyset().toByteArray();
393 
394     KeysetWriteEncryptedResponse writeResponse1 =
395         keysetWriteEncrypted(keysetStub, keyset, invalidData, /*associatedData=*/ Optional.empty());
396     assertThat(writeResponse1.getErr()).isNotEmpty();
397 
398     KeysetWriteEncryptedResponse writeResponse2 =
399         keysetWriteEncrypted(
400             keysetStub, invalidData, masterKeyset, /*associatedData=*/ Optional.empty());
401     assertThat(writeResponse2.getErr()).isNotEmpty();
402 
403     KeysetReadEncryptedResponse readResponse1 =
404         keysetReadEncrypted(keysetStub, keyset, invalidData, /*associatedData=*/ Optional.empty());
405     assertThat(readResponse1.getErr()).isNotEmpty();
406 
407     KeysetReadEncryptedResponse readResponse2 =
408         keysetReadEncrypted(
409             keysetStub, invalidData, masterKeyset, /*associatedData=*/ Optional.empty());
410     assertThat(readResponse2.getErr()).isNotEmpty();
411   }
412 
413   // TODO(juerg): Add tests for KEYSET_WRITER_JSON.
414 
415   @Test
aeadCreateKeyset_success()416   public void aeadCreateKeyset_success() throws Exception {
417     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
418     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
419     assertThat(keysetResponse.getErr()).isEmpty();
420     CreationResponse response =
421         aeadStub.create(
422             CreationRequest.newBuilder()
423                 .setAnnotatedKeyset(
424                     AnnotatedKeyset.newBuilder()
425                         .setSerializedKeyset(keysetResponse.getKeyset())
426                         .build())
427                 .build());
428     assertThat(response.getErr()).isEmpty();
429   }
430 
431   @Test
aeadCreateKeyset_fails()432   public void aeadCreateKeyset_fails() throws Exception {
433     CreationResponse response =
434         aeadStub.create(
435             CreationRequest.newBuilder()
436                 .setAnnotatedKeyset(
437                     AnnotatedKeyset.newBuilder()
438                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
439                         .build())
440                 .build());
441     assertThat(response.getErr()).isNotEmpty();
442   }
443 
aeadEncrypt( AeadGrpc.AeadBlockingStub aeadStub, byte[] keyset, byte[] plaintext, byte[] associatedData)444   private static AeadEncryptResponse aeadEncrypt(
445       AeadGrpc.AeadBlockingStub aeadStub, byte[] keyset, byte[] plaintext, byte[] associatedData) {
446     AeadEncryptRequest encRequest =
447         AeadEncryptRequest.newBuilder()
448             .setAnnotatedKeyset(
449                 AnnotatedKeyset.newBuilder()
450                     .setSerializedKeyset(ByteString.copyFrom(keyset))
451                     .build())
452             .setPlaintext(ByteString.copyFrom(plaintext))
453             .setAssociatedData(ByteString.copyFrom(associatedData))
454             .build();
455     return aeadStub.encrypt(encRequest);
456   }
457 
aeadDecrypt( AeadGrpc.AeadBlockingStub aeadStub, byte[] keyset, byte[] ciphertext, byte[] associatedData)458   private static AeadDecryptResponse aeadDecrypt(
459       AeadGrpc.AeadBlockingStub aeadStub, byte[] keyset, byte[] ciphertext, byte[] associatedData) {
460     AeadDecryptRequest decRequest =
461         AeadDecryptRequest.newBuilder()
462             .setAnnotatedKeyset(
463                 AnnotatedKeyset.newBuilder()
464                     .setSerializedKeyset(ByteString.copyFrom(keyset))
465                     .build())
466             .setCiphertext(ByteString.copyFrom(ciphertext))
467             .setAssociatedData(ByteString.copyFrom(associatedData))
468             .build();
469     return aeadStub.decrypt(decRequest);
470   }
471 
472   @Test
aeadGenerateEncryptDecrypt_success()473   public void aeadGenerateEncryptDecrypt_success() throws Exception {
474     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
475     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
476     byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
477 
478     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
479     assertThat(keysetResponse.getErr()).isEmpty();
480     byte[] keyset = keysetResponse.getKeyset().toByteArray();
481 
482     AeadEncryptResponse encResponse = aeadEncrypt(aeadStub, keyset, plaintext, associatedData);
483     assertThat(encResponse.getErr()).isEmpty();
484     byte[] ciphertext = encResponse.getCiphertext().toByteArray();
485 
486     AeadDecryptResponse decResponse = aeadDecrypt(aeadStub, keyset, ciphertext, associatedData);
487     assertThat(decResponse.getErr()).isEmpty();
488     byte[] output = decResponse.getPlaintext().toByteArray();
489 
490     assertThat(output).isEqualTo(plaintext);
491   }
492 
493   @Test
generateKeyset_failsOnBadTemplate()494   public void generateKeyset_failsOnBadTemplate() throws Exception {
495     byte[] badTemplate = "bad template".getBytes(UTF_8);
496     KeysetGenerateResponse genResponse = generateKeyset(keysetStub, badTemplate);
497     assertThat(genResponse.getErr()).isNotEmpty();
498   }
499 
500   @Test
aeadDecrypt_failsOnBadCiphertext()501   public void aeadDecrypt_failsOnBadCiphertext() throws Exception {
502     byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
503     byte[] badCiphertext = "bad ciphertext".getBytes(UTF_8);
504     byte[] associatedData = "aead_decrypt_fails_on_bad_ciphertext".getBytes(UTF_8);
505 
506     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
507     assertThat(keysetResponse.getErr()).isEmpty();
508     byte[] keyset = keysetResponse.getKeyset().toByteArray();
509 
510     AeadDecryptResponse decResponse = aeadDecrypt(aeadStub, keyset, badCiphertext, associatedData);
511     assertThat(decResponse.getErr()).isNotEmpty();
512   }
513 
514   @Test
deterministicAeadCreateKeyset_success()515   public void deterministicAeadCreateKeyset_success() throws Exception {
516     byte[] template = KeyTemplateProtoConverter.toByteArray(AesSivKeyManager.aes256SivTemplate());
517     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
518     assertThat(keysetResponse.getErr()).isEmpty();
519     CreationResponse response =
520         daeadStub.create(
521             CreationRequest.newBuilder()
522                 .setAnnotatedKeyset(
523                     AnnotatedKeyset.newBuilder().setSerializedKeyset(keysetResponse.getKeyset()))
524                 .build());
525     assertThat(response.getErr()).isEmpty();
526   }
527 
528   @Test
deterministicAeadCreateKeyset_fails()529   public void deterministicAeadCreateKeyset_fails() throws Exception {
530     CreationResponse response =
531         daeadStub.create(
532             CreationRequest.newBuilder()
533                 .setAnnotatedKeyset(
534                     AnnotatedKeyset.newBuilder()
535                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80})))
536                 .build());
537     assertThat(response.getErr()).isNotEmpty();
538   }
539 
daeadEncrypt( DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub, byte[] keyset, byte[] plaintext, byte[] associatedData)540   private static DeterministicAeadEncryptResponse daeadEncrypt(
541       DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub,
542       byte[] keyset,
543       byte[] plaintext,
544       byte[] associatedData) {
545     DeterministicAeadEncryptRequest encRequest =
546         DeterministicAeadEncryptRequest.newBuilder()
547             .setAnnotatedKeyset(
548                 AnnotatedKeyset.newBuilder().setSerializedKeyset(ByteString.copyFrom(keyset)))
549             .setPlaintext(ByteString.copyFrom(plaintext))
550             .setAssociatedData(ByteString.copyFrom(associatedData))
551             .build();
552     return daeadStub.encryptDeterministically(encRequest);
553   }
554 
daeadDecrypt( DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub, byte[] keyset, byte[] ciphertext, byte[] associatedData)555   private static DeterministicAeadDecryptResponse daeadDecrypt(
556       DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub,
557       byte[] keyset,
558       byte[] ciphertext,
559       byte[] associatedData) {
560     DeterministicAeadDecryptRequest decRequest =
561         DeterministicAeadDecryptRequest.newBuilder()
562             .setAnnotatedKeyset(
563                 AnnotatedKeyset.newBuilder()
564                     .setSerializedKeyset(ByteString.copyFrom(keyset))
565                     .build())
566             .setCiphertext(ByteString.copyFrom(ciphertext))
567             .setAssociatedData(ByteString.copyFrom(associatedData))
568             .build();
569     return daeadStub.decryptDeterministically(decRequest);
570   }
571 
572   @Test
daeadGenerateEncryptDecryptDeterministically_success()573   public void daeadGenerateEncryptDecryptDeterministically_success() throws Exception {
574     byte[] template = KeyTemplateProtoConverter.toByteArray(AesSivKeyManager.aes256SivTemplate());
575     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
576     byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
577 
578     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
579     assertThat(keysetResponse.getErr()).isEmpty();
580     byte[] keyset = keysetResponse.getKeyset().toByteArray();
581 
582     DeterministicAeadEncryptResponse encResponse =
583         daeadEncrypt(daeadStub, keyset, plaintext, associatedData);
584     assertThat(encResponse.getErr()).isEmpty();
585     byte[] ciphertext = encResponse.getCiphertext().toByteArray();
586 
587     DeterministicAeadDecryptResponse decResponse =
588         daeadDecrypt(daeadStub, keyset, ciphertext, associatedData);
589     assertThat(decResponse.getErr()).isEmpty();
590     byte[] output = decResponse.getPlaintext().toByteArray();
591 
592     assertThat(output).isEqualTo(plaintext);
593   }
594 
595   @Test
daeadEncryptDeterministically_failsOnBadKeyset()596   public void daeadEncryptDeterministically_failsOnBadKeyset() throws Exception {
597     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
598     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
599     byte[] associatedData = "aead_encrypt_fails_on_bad_keyset".getBytes(UTF_8);
600     assertThrows(
601         StatusRuntimeException.class,
602         () -> daeadEncrypt(daeadStub, badKeyset, plaintext, associatedData));
603   }
604 
605   @Test
daeadDecryptDeterministically_failsOnBadCiphertext()606   public void daeadDecryptDeterministically_failsOnBadCiphertext() throws Exception {
607     byte[] template = KeyTemplateProtoConverter.toByteArray(AesSivKeyManager.aes256SivTemplate());
608     byte[] badCiphertext = "bad ciphertext".getBytes(UTF_8);
609     byte[] associatedData = "aead_decrypt_fails_on_bad_ciphertext".getBytes(UTF_8);
610 
611     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
612     assertThat(keysetResponse.getErr()).isEmpty();
613     byte[] keyset = keysetResponse.getKeyset().toByteArray();
614 
615     DeterministicAeadDecryptResponse decResponse =
616         daeadDecrypt(daeadStub, keyset, badCiphertext, associatedData);
617     assertThat(decResponse.getErr()).isNotEmpty();
618   }
619 
620   @Test
daeadDecryptDeterministically_failsOnBadKeyset()621   public void daeadDecryptDeterministically_failsOnBadKeyset() throws Exception {
622     byte[] template = KeyTemplateProtoConverter.toByteArray(AesSivKeyManager.aes256SivTemplate());
623     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
624     byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
625 
626     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
627     assertThat(keysetResponse.getErr()).isEmpty();
628     byte[] keyset = keysetResponse.getKeyset().toByteArray();
629 
630     DeterministicAeadEncryptResponse encResponse =
631         daeadEncrypt(daeadStub, keyset, plaintext, associatedData);
632     assertThat(encResponse.getErr()).isEmpty();
633     byte[] ciphertext = encResponse.getCiphertext().toByteArray();
634 
635     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
636     assertThrows(
637         StatusRuntimeException.class,
638         () -> daeadDecrypt(daeadStub, badKeyset, ciphertext, associatedData));
639   }
640 
641   @Test
streamingAeadCreateKeyset_success()642   public void streamingAeadCreateKeyset_success() throws Exception {
643     byte[] template =
644         KeyTemplateProtoConverter.toByteArray(
645             AesGcmHkdfStreamingKeyManager.aes128GcmHkdf4KBTemplate());
646     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
647     assertThat(keysetResponse.getErr()).isEmpty();
648     CreationResponse response =
649         streamingAeadStub.create(
650             CreationRequest.newBuilder()
651                 .setAnnotatedKeyset(
652                     AnnotatedKeyset.newBuilder()
653                         .setSerializedKeyset(keysetResponse.getKeyset())
654                         .build())
655                 .build());
656     assertThat(response.getErr()).isEmpty();
657   }
658 
659   @Test
streamingAeadCreateKeyset_fails()660   public void streamingAeadCreateKeyset_fails() throws Exception {
661     CreationResponse response =
662         streamingAeadStub.create(
663             CreationRequest.newBuilder()
664                 .setAnnotatedKeyset(
665                     AnnotatedKeyset.newBuilder()
666                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
667                         .build())
668                 .build());
669     assertThat(response.getErr()).isNotEmpty();
670   }
671 
streamingAeadEncrypt( StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub, byte[] keyset, byte[] plaintext, byte[] associatedData)672   private static StreamingAeadEncryptResponse streamingAeadEncrypt(
673       StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub,
674       byte[] keyset,
675       byte[] plaintext,
676       byte[] associatedData) {
677     StreamingAeadEncryptRequest encRequest =
678         StreamingAeadEncryptRequest.newBuilder()
679             .setAnnotatedKeyset(
680                 AnnotatedKeyset.newBuilder()
681                     .setSerializedKeyset(ByteString.copyFrom(keyset))
682                     .build())
683             .setPlaintext(ByteString.copyFrom(plaintext))
684             .setAssociatedData(ByteString.copyFrom(associatedData))
685             .build();
686     return streamingAeadStub.encrypt(encRequest);
687   }
688 
streamingAeadDecrypt( StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub, byte[] keyset, byte[] ciphertext, byte[] associatedData)689   private static StreamingAeadDecryptResponse streamingAeadDecrypt(
690       StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub,
691       byte[] keyset,
692       byte[] ciphertext,
693       byte[] associatedData) {
694     StreamingAeadDecryptRequest decRequest =
695         StreamingAeadDecryptRequest.newBuilder()
696             .setAnnotatedKeyset(
697                 AnnotatedKeyset.newBuilder()
698                     .setSerializedKeyset(ByteString.copyFrom(keyset))
699                     .build())
700             .setCiphertext(ByteString.copyFrom(ciphertext))
701             .setAssociatedData(ByteString.copyFrom(associatedData))
702             .build();
703     return streamingAeadStub.decrypt(decRequest);
704   }
705 
706   @Test
streamingAeadGenerateEncryptDecrypt_success()707   public void streamingAeadGenerateEncryptDecrypt_success() throws Exception {
708     byte[] template =
709         KeyTemplateProtoConverter.toByteArray(
710             AesGcmHkdfStreamingKeyManager.aes128GcmHkdf4KBTemplate());
711     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
712     byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
713 
714     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
715     assertThat(keysetResponse.getErr()).isEmpty();
716     byte[] keyset = keysetResponse.getKeyset().toByteArray();
717 
718     StreamingAeadEncryptResponse encResponse =
719         streamingAeadEncrypt(streamingAeadStub, keyset, plaintext, associatedData);
720     assertThat(encResponse.getErr()).isEmpty();
721     byte[] ciphertext = encResponse.getCiphertext().toByteArray();
722 
723     StreamingAeadDecryptResponse decResponse =
724         streamingAeadDecrypt(streamingAeadStub, keyset, ciphertext, associatedData);
725     assertThat(decResponse.getErr()).isEmpty();
726     byte[] output = decResponse.getPlaintext().toByteArray();
727 
728     assertThat(output).isEqualTo(plaintext);
729   }
730 
731   @Test
streamingAeadEncrypt_failsOnBadKeyset()732   public void streamingAeadEncrypt_failsOnBadKeyset() throws Exception {
733     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
734     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
735     byte[] associatedData = "streamingAead_encrypt_fails_on_bad_keyset".getBytes(UTF_8);
736     StreamingAeadEncryptResponse encResponse =
737         streamingAeadEncrypt(streamingAeadStub, badKeyset, plaintext, associatedData);
738     assertThat(encResponse.getErr()).isNotEmpty();
739   }
740 
741   @Test
streamingAeadDecrypt_failsOnBadCiphertext()742   public void streamingAeadDecrypt_failsOnBadCiphertext() throws Exception {
743     byte[] template =
744         KeyTemplateProtoConverter.toByteArray(
745             AesGcmHkdfStreamingKeyManager.aes128GcmHkdf4KBTemplate());
746     byte[] badCiphertext = "bad ciphertext".getBytes(UTF_8);
747     byte[] associatedData = "streamingAead_decrypt_fails_on_bad_ciphertext".getBytes(UTF_8);
748 
749     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
750     assertThat(keysetResponse.getErr()).isEmpty();
751     byte[] keyset = keysetResponse.getKeyset().toByteArray();
752 
753     StreamingAeadDecryptResponse decResponse =
754         streamingAeadDecrypt(streamingAeadStub, keyset, badCiphertext, associatedData);
755     assertThat(decResponse.getErr()).isNotEmpty();
756   }
757 
758   @Test
streamingAeadDecrypt_failsOnBadKeyset()759   public void streamingAeadDecrypt_failsOnBadKeyset() throws Exception {
760     byte[] template =
761         KeyTemplateProtoConverter.toByteArray(
762             AesGcmHkdfStreamingKeyManager.aes128GcmHkdf4KBTemplate());
763     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
764     byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
765 
766     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
767     assertThat(keysetResponse.getErr()).isEmpty();
768     byte[] keyset = keysetResponse.getKeyset().toByteArray();
769 
770     StreamingAeadEncryptResponse encResponse =
771         streamingAeadEncrypt(streamingAeadStub, keyset, plaintext, associatedData);
772     assertThat(encResponse.getErr()).isEmpty();
773     byte[] ciphertext = encResponse.getCiphertext().toByteArray();
774 
775     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
776 
777     StreamingAeadDecryptResponse decResponse =
778         streamingAeadDecrypt(streamingAeadStub, badKeyset, ciphertext, associatedData);
779     assertThat(decResponse.getErr()).isNotEmpty();
780   }
781 
782   @Test
macCreateKeyset_success()783   public void macCreateKeyset_success() throws Exception {
784     byte[] template =
785         KeyTemplateProtoConverter.toByteArray(HmacKeyManager.hmacSha256HalfDigestTemplate());
786     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
787     assertThat(keysetResponse.getErr()).isEmpty();
788     CreationResponse response =
789         macStub.create(
790             CreationRequest.newBuilder()
791                 .setAnnotatedKeyset(
792                     AnnotatedKeyset.newBuilder()
793                         .setSerializedKeyset(keysetResponse.getKeyset())
794                         .build())
795                 .build());
796     assertThat(response.getErr()).isEmpty();
797   }
798 
799   @Test
macCreateKeyset_fails()800   public void macCreateKeyset_fails() throws Exception {
801     CreationResponse response =
802         macStub.create(
803             CreationRequest.newBuilder()
804                 .setAnnotatedKeyset(
805                     AnnotatedKeyset.newBuilder()
806                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
807                         .build())
808                 .build());
809     assertThat(response.getErr()).isNotEmpty();
810   }
811 
computeMac( MacGrpc.MacBlockingStub macStub, byte[] keyset, byte[] data)812   private static ComputeMacResponse computeMac(
813       MacGrpc.MacBlockingStub macStub, byte[] keyset, byte[] data) {
814     ComputeMacRequest request =
815         ComputeMacRequest.newBuilder()
816             .setAnnotatedKeyset(
817                 AnnotatedKeyset.newBuilder()
818                     .setSerializedKeyset(ByteString.copyFrom(keyset))
819                     .build())
820             .setData(ByteString.copyFrom(data))
821             .build();
822     return macStub.computeMac(request);
823   }
824 
verifyMac( MacGrpc.MacBlockingStub macStub, byte[] keyset, byte[] macValue, byte[] data)825   private static VerifyMacResponse verifyMac(
826       MacGrpc.MacBlockingStub macStub, byte[] keyset, byte[] macValue, byte[] data) {
827     VerifyMacRequest request =
828         VerifyMacRequest.newBuilder()
829             .setAnnotatedKeyset(
830                 AnnotatedKeyset.newBuilder()
831                     .setSerializedKeyset(ByteString.copyFrom(keyset))
832                     .build())
833             .setMacValue(ByteString.copyFrom(macValue))
834             .setData(ByteString.copyFrom(data))
835             .build();
836     return macStub.verifyMac(request);
837   }
838 
839   @Test
computeVerifyMac_success()840   public void computeVerifyMac_success() throws Exception {
841     byte[] template =
842         KeyTemplateProtoConverter.toByteArray(HmacKeyManager.hmacSha256HalfDigestTemplate());
843     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
844 
845     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
846     assertThat(keysetResponse.getErr()).isEmpty();
847     byte[] keyset = keysetResponse.getKeyset().toByteArray();
848 
849     ComputeMacResponse compResponse = computeMac(macStub, keyset, data);
850     assertThat(compResponse.getErr()).isEmpty();
851     byte[] macValue = compResponse.getMacValue().toByteArray();
852 
853     VerifyMacResponse verifyResponse = verifyMac(macStub, keyset, macValue, data);
854     assertThat(verifyResponse.getErr()).isEmpty();
855   }
856 
857   @Test
computeMac_failsOnBadKeyset()858   public void computeMac_failsOnBadKeyset() throws Exception {
859     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
860     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
861 
862     ComputeMacResponse compResponse = computeMac(macStub, badKeyset, data);
863     assertThat(compResponse.getErr()).isNotEmpty();
864   }
865 
866   @Test
verifyMac_failsOnBadMacValue()867   public void verifyMac_failsOnBadMacValue() throws Exception {
868     byte[] template =
869         KeyTemplateProtoConverter.toByteArray(HmacKeyManager.hmacSha256HalfDigestTemplate());
870     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
871 
872     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
873     assertThat(keysetResponse.getErr()).isEmpty();
874     byte[] keyset = keysetResponse.getKeyset().toByteArray();
875 
876     VerifyMacResponse verifyResponse =
877         verifyMac(macStub, keyset, "bad mac_value".getBytes(UTF_8), data);
878     assertThat(verifyResponse.getErr()).isNotEmpty();
879   }
880 
881   @Test
verifyMac_failsOnBadKeyset()882   public void verifyMac_failsOnBadKeyset() throws Exception {
883     byte[] template =
884         KeyTemplateProtoConverter.toByteArray(HmacKeyManager.hmacSha256HalfDigestTemplate());
885     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
886 
887     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
888     assertThat(keysetResponse.getErr()).isEmpty();
889     byte[] keyset = keysetResponse.getKeyset().toByteArray();
890 
891     ComputeMacResponse compResponse = computeMac(macStub, keyset, data);
892     assertThat(compResponse.getErr()).isEmpty();
893     byte[] macValue = compResponse.getMacValue().toByteArray();
894 
895     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
896     VerifyMacResponse verifyResponse = verifyMac(macStub, badKeyset, macValue, data);
897     assertThat(verifyResponse.getErr()).isNotEmpty();
898   }
899 
900   @Test
prfSetCreateKeyset_success()901   public void prfSetCreateKeyset_success() throws Exception {
902     byte[] template = KeyTemplateProtoConverter.toByteArray(HmacPrfKeyManager.hmacSha256Template());
903     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
904     assertThat(keysetResponse.getErr()).isEmpty();
905     CreationResponse response =
906         prfSetStub.create(
907             CreationRequest.newBuilder()
908                 .setAnnotatedKeyset(
909                     AnnotatedKeyset.newBuilder()
910                         .setSerializedKeyset(keysetResponse.getKeyset())
911                         .build())
912                 .build());
913     assertThat(response.getErr()).isEmpty();
914   }
915 
916   @Test
prfSetCreateKeyset_fails()917   public void prfSetCreateKeyset_fails() throws Exception {
918     CreationResponse response =
919         prfSetStub.create(
920             CreationRequest.newBuilder()
921                 .setAnnotatedKeyset(
922                     AnnotatedKeyset.newBuilder()
923                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
924                         .build())
925                 .build());
926     assertThat(response.getErr()).isNotEmpty();
927   }
928 
keyIds( PrfSetGrpc.PrfSetBlockingStub prfSetStub, byte[] keyset)929   private static PrfSetKeyIdsResponse keyIds(
930       PrfSetGrpc.PrfSetBlockingStub prfSetStub, byte[] keyset) {
931     PrfSetKeyIdsRequest request =
932         PrfSetKeyIdsRequest.newBuilder()
933             .setAnnotatedKeyset(
934                 AnnotatedKeyset.newBuilder()
935                     .setSerializedKeyset(ByteString.copyFrom(keyset))
936                     .build())
937             .build();
938     return prfSetStub.keyIds(request);
939   }
940 
computePrf( PrfSetGrpc.PrfSetBlockingStub prfSetStub, byte[] keyset, int keyId, byte[] inputData, int outputLength)941   private static PrfSetComputeResponse computePrf(
942       PrfSetGrpc.PrfSetBlockingStub prfSetStub,
943       byte[] keyset,
944       int keyId,
945       byte[] inputData,
946       int outputLength) {
947     PrfSetComputeRequest request =
948         PrfSetComputeRequest.newBuilder()
949             .setAnnotatedKeyset(
950                 AnnotatedKeyset.newBuilder()
951                     .setSerializedKeyset(ByteString.copyFrom(keyset))
952                     .build())
953             .setKeyId(keyId)
954             .setInputData(ByteString.copyFrom(inputData))
955             .setOutputLength(outputLength)
956             .build();
957     return prfSetStub.compute(request);
958   }
959 
960   @Test
computePrf_success()961   public void computePrf_success() throws Exception {
962     byte[] template = KeyTemplateProtoConverter.toByteArray(
963         HmacPrfKeyManager.hmacSha256Template());
964     byte[] inputData = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
965     int outputLength = 15;
966 
967     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
968     assertThat(keysetResponse.getErr()).isEmpty();
969     byte[] keyset = keysetResponse.getKeyset().toByteArray();
970 
971     PrfSetKeyIdsResponse keyIdsResponse = keyIds(prfSetStub, keyset);
972     assertThat(keyIdsResponse.getErr()).isEmpty();
973     int primaryKeyId = keyIdsResponse.getOutput().getPrimaryKeyId();
974 
975     PrfSetComputeResponse computeResponse = computePrf(
976         prfSetStub, keyset, primaryKeyId, inputData, outputLength);
977     assertThat(computeResponse.getErr()).isEmpty();
978     assertThat(computeResponse.getOutput().size()).isEqualTo(outputLength);
979   }
980 
981   @Test
prfKeyIds_failsOnBadKeyset()982   public void prfKeyIds_failsOnBadKeyset() throws Exception {
983     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
984 
985     PrfSetKeyIdsResponse keyIdsResponse = keyIds(prfSetStub, badKeyset);
986     assertThat(keyIdsResponse.getErr()).isNotEmpty();
987   }
988 
989   @Test
computePrf_failsOnUnknownKeyId()990   public void computePrf_failsOnUnknownKeyId() throws Exception {
991     byte[] template = KeyTemplateProtoConverter.toByteArray(
992         HmacPrfKeyManager.hmacSha256Template());
993     byte[] inputData = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
994     int outputLength = 15;
995     int badKeyId = 123456789;
996 
997     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
998     assertThat(keysetResponse.getErr()).isEmpty();
999     byte[] keyset = keysetResponse.getKeyset().toByteArray();
1000 
1001     PrfSetComputeResponse computeResponse = computePrf(
1002         prfSetStub, keyset, badKeyId, inputData, outputLength);
1003     assertThat(computeResponse.getErr()).isNotEmpty();
1004   }
1005 
1006   @Test
computePrf_failsOnBadOutputLength()1007   public void computePrf_failsOnBadOutputLength() throws Exception {
1008     byte[] template = KeyTemplateProtoConverter.toByteArray(
1009         HmacPrfKeyManager.hmacSha256Template());
1010     byte[] inputData = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
1011     int outputLength = 12345;
1012 
1013     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
1014     assertThat(keysetResponse.getErr()).isEmpty();
1015     byte[] keyset = keysetResponse.getKeyset().toByteArray();
1016 
1017     PrfSetKeyIdsResponse keyIdsResponse = keyIds(prfSetStub, keyset);
1018     assertThat(keyIdsResponse.getErr()).isEmpty();
1019     int primaryKeyId = keyIdsResponse.getOutput().getPrimaryKeyId();
1020 
1021     PrfSetComputeResponse computeResponse = computePrf(
1022         prfSetStub, keyset, primaryKeyId, inputData, outputLength);
1023     assertThat(computeResponse.getErr()).isNotEmpty();
1024   }
1025 
1026   @Test
getServerInfo_success()1027   public void getServerInfo_success() throws Exception {
1028     ServerInfoResponse response =
1029         metadataStub.getServerInfo(ServerInfoRequest.getDefaultInstance());
1030     assertThat(response.getLanguage()).isEqualTo("java");
1031     assertThat(response.getTinkVersion()).isNotEmpty();
1032   }
1033 }
1034