• 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.config.TinkConfig;
25 import com.google.crypto.tink.hybrid.EciesAeadHkdfPrivateKeyManager;
26 import com.google.crypto.tink.internal.KeyTemplateProtoConverter;
27 import com.google.crypto.tink.signature.EcdsaSignKeyManager;
28 import com.google.crypto.tink.testing.proto.AnnotatedKeyset;
29 import com.google.crypto.tink.testing.proto.CreationRequest;
30 import com.google.crypto.tink.testing.proto.CreationResponse;
31 import com.google.crypto.tink.testing.proto.HybridDecryptRequest;
32 import com.google.crypto.tink.testing.proto.HybridDecryptResponse;
33 import com.google.crypto.tink.testing.proto.HybridEncryptRequest;
34 import com.google.crypto.tink.testing.proto.HybridEncryptResponse;
35 import com.google.crypto.tink.testing.proto.HybridGrpc;
36 import com.google.crypto.tink.testing.proto.KeysetGenerateRequest;
37 import com.google.crypto.tink.testing.proto.KeysetGenerateResponse;
38 import com.google.crypto.tink.testing.proto.KeysetGrpc;
39 import com.google.crypto.tink.testing.proto.KeysetPublicRequest;
40 import com.google.crypto.tink.testing.proto.KeysetPublicResponse;
41 import com.google.crypto.tink.testing.proto.SignatureGrpc;
42 import com.google.crypto.tink.testing.proto.SignatureSignRequest;
43 import com.google.crypto.tink.testing.proto.SignatureSignResponse;
44 import com.google.crypto.tink.testing.proto.SignatureVerifyRequest;
45 import com.google.crypto.tink.testing.proto.SignatureVerifyResponse;
46 import com.google.protobuf.ByteString;
47 import io.grpc.ManagedChannel;
48 import io.grpc.Server;
49 import io.grpc.inprocess.InProcessChannelBuilder;
50 import io.grpc.inprocess.InProcessServerBuilder;
51 import org.junit.After;
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.junit.runners.JUnit4;
56 
57 @RunWith(JUnit4.class)
58 public final class AsymmetricTestingServicesTest {
59   private Server server;
60   private ManagedChannel channel;
61   KeysetGrpc.KeysetBlockingStub keysetStub;
62   HybridGrpc.HybridBlockingStub hybridStub;
63   SignatureGrpc.SignatureBlockingStub signatureStub;
64 
65   @Before
setUp()66   public void setUp() throws Exception {
67     TinkConfig.register();
68     String serverName = InProcessServerBuilder.generateName();
69     server =
70         InProcessServerBuilder.forName(serverName)
71             .directExecutor()
72             .addService(new KeysetServiceImpl())
73             .addService(new HybridServiceImpl())
74             .addService(new SignatureServiceImpl())
75             .build()
76             .start();
77     channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
78     keysetStub = KeysetGrpc.newBlockingStub(channel);
79     hybridStub = HybridGrpc.newBlockingStub(channel);
80     signatureStub = SignatureGrpc.newBlockingStub(channel);
81   }
82 
83   @After
tearDown()84   public void tearDown() throws Exception {
85     assertThat(channel.shutdown().awaitTermination(5, SECONDS)).isTrue();
86     assertThat(server.shutdown().awaitTermination(5, SECONDS)).isTrue();
87   }
88 
generateKeyset( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] template)89   private static KeysetGenerateResponse generateKeyset(
90       KeysetGrpc.KeysetBlockingStub keysetStub, byte[] template) {
91     KeysetGenerateRequest genRequest =
92         KeysetGenerateRequest.newBuilder().setTemplate(ByteString.copyFrom(template)).build();
93     return keysetStub.generate(genRequest);
94   }
95 
publicKeyset( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] privateKeyset)96   private static KeysetPublicResponse publicKeyset(
97       KeysetGrpc.KeysetBlockingStub keysetStub, byte[] privateKeyset) {
98     KeysetPublicRequest request =
99         KeysetPublicRequest.newBuilder()
100             .setPrivateKeyset(ByteString.copyFrom(privateKeyset))
101             .build();
102     return keysetStub.public_(request);
103   }
104 
105   @Test
hybridDecryptCreateKeyset_success()106   public void hybridDecryptCreateKeyset_success() throws Exception {
107     byte[] template =
108         KeyTemplateProtoConverter.toByteArray(
109             EciesAeadHkdfPrivateKeyManager.eciesP256HkdfHmacSha256Aes128GcmTemplate());
110     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
111     assertThat(keysetResponse.getErr()).isEmpty();
112     CreationResponse response =
113         hybridStub.createHybridDecrypt(
114             CreationRequest.newBuilder()
115                 .setAnnotatedKeyset(
116                     AnnotatedKeyset.newBuilder()
117                         .setSerializedKeyset(keysetResponse.getKeyset())
118                         .build())
119                 .build());
120     assertThat(response.getErr()).isEmpty();
121   }
122 
123   @Test
hybridDecryptCreateKeyset_fails()124   public void hybridDecryptCreateKeyset_fails() throws Exception {
125     CreationResponse response =
126         hybridStub.createHybridDecrypt(
127             CreationRequest.newBuilder()
128                 .setAnnotatedKeyset(
129                     AnnotatedKeyset.newBuilder()
130                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
131                         .build())
132                 .build());
133     assertThat(response.getErr()).isNotEmpty();
134   }
135 
136 
137   @Test
hybridEncryptCreateKeyset_success()138   public void hybridEncryptCreateKeyset_success() throws Exception {
139     byte[] template = KeyTemplateProtoConverter.toByteArray(
140         EciesAeadHkdfPrivateKeyManager.eciesP256HkdfHmacSha256Aes128GcmTemplate());
141     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
142     assertThat(keysetResponse.getErr()).isEmpty();
143     byte[] privateKeyset = keysetResponse.getKeyset().toByteArray();
144 
145     KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset);
146     assertThat(pubResponse.getErr()).isEmpty();
147     CreationResponse response =
148         hybridStub.createHybridEncrypt(
149             CreationRequest.newBuilder()
150                 .setAnnotatedKeyset(
151                     AnnotatedKeyset.newBuilder()
152                         .setSerializedKeyset(pubResponse.getPublicKeyset())
153                         .build())
154                 .build());
155     assertThat(response.getErr()).isEmpty();
156   }
157 
158   @Test
hybridEncryptCreateKeyset_fails()159   public void hybridEncryptCreateKeyset_fails() throws Exception {
160     CreationResponse response =
161         hybridStub.createHybridEncrypt(
162             CreationRequest.newBuilder()
163                 .setAnnotatedKeyset(
164                     AnnotatedKeyset.newBuilder()
165                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
166                         .build())
167                 .build());
168     assertThat(response.getErr()).isNotEmpty();
169   }
170 
hybridEncrypt( HybridGrpc.HybridBlockingStub hybridStub, byte[] publicKeyset, byte[] plaintext, byte[] contextInfo)171   private static HybridEncryptResponse hybridEncrypt(
172       HybridGrpc.HybridBlockingStub hybridStub,
173       byte[] publicKeyset,
174       byte[] plaintext,
175       byte[] contextInfo) {
176     HybridEncryptRequest encRequest =
177         HybridEncryptRequest.newBuilder()
178             .setPublicAnnotatedKeyset(
179                 AnnotatedKeyset.newBuilder()
180                     .setSerializedKeyset(ByteString.copyFrom(publicKeyset))
181                     .build())
182             .setPlaintext(ByteString.copyFrom(plaintext))
183             .setContextInfo(ByteString.copyFrom(contextInfo))
184             .build();
185     return hybridStub.encrypt(encRequest);
186   }
187 
hybridDecrypt( HybridGrpc.HybridBlockingStub hybridStub, byte[] privateKeyset, byte[] ciphertext, byte[] contextInfo)188   private static HybridDecryptResponse hybridDecrypt(
189       HybridGrpc.HybridBlockingStub hybridStub,
190       byte[] privateKeyset,
191       byte[] ciphertext,
192       byte[] contextInfo) {
193     HybridDecryptRequest decRequest =
194         HybridDecryptRequest.newBuilder()
195             .setPrivateAnnotatedKeyset(
196                 AnnotatedKeyset.newBuilder()
197                     .setSerializedKeyset(ByteString.copyFrom(privateKeyset))
198                     .build())
199             .setCiphertext(ByteString.copyFrom(ciphertext))
200             .setContextInfo(ByteString.copyFrom(contextInfo))
201             .build();
202     return hybridStub.decrypt(decRequest);
203   }
204 
205   @Test
hybridGenerateEncryptDecrypt_success()206   public void hybridGenerateEncryptDecrypt_success() throws Exception {
207     byte[] template = KeyTemplateProtoConverter.toByteArray(
208         EciesAeadHkdfPrivateKeyManager.eciesP256HkdfHmacSha256Aes128GcmTemplate());
209     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
210     byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
211 
212     KeysetGenerateResponse genResponse = generateKeyset(keysetStub, template);
213     assertThat(genResponse.getErr()).isEmpty();
214     byte[] privateKeyset = genResponse.getKeyset().toByteArray();
215 
216     KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset);
217     assertThat(pubResponse.getErr()).isEmpty();
218     byte[] publicKeyset = pubResponse.getPublicKeyset().toByteArray();
219 
220     HybridEncryptResponse encResponse =
221         hybridEncrypt(hybridStub, publicKeyset, plaintext, associatedData);
222     assertThat(encResponse.getErr()).isEmpty();
223     byte[] ciphertext = encResponse.getCiphertext().toByteArray();
224 
225     HybridDecryptResponse decResponse =
226         hybridDecrypt(hybridStub, privateKeyset, ciphertext, associatedData);
227     assertThat(decResponse.getErr()).isEmpty();
228     byte[] output = decResponse.getPlaintext().toByteArray();
229 
230     assertThat(output).isEqualTo(plaintext);
231   }
232 
233   @Test
publicKeyset_failsOnBadKeyset()234   public void publicKeyset_failsOnBadKeyset() throws Exception {
235     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
236     KeysetPublicResponse response = publicKeyset(keysetStub, badKeyset);
237     assertThat(response.getErr()).isNotEmpty();
238   }
239 
240   @Test
hybridEncrypt_errorOnBadKeyset()241   public void hybridEncrypt_errorOnBadKeyset() throws Exception {
242     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
243     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
244     byte[] contextInfo = "hybrid_encrypt_bad_keyset".getBytes(UTF_8);
245     assertThrows(
246         io.grpc.StatusRuntimeException.class,
247         () -> hybridEncrypt(hybridStub, badKeyset, plaintext, contextInfo));
248   }
249 
250   @Test
hybridDecrypt_errorOnBadCiphertext()251   public void hybridDecrypt_errorOnBadCiphertext() throws Exception {
252     byte[] template = KeyTemplateProtoConverter.toByteArray(
253         EciesAeadHkdfPrivateKeyManager.eciesP256HkdfHmacSha256Aes128GcmTemplate());
254     byte[] badCiphertext = "bad ciphertext".getBytes(UTF_8);
255     byte[] contextInfo = "hybrid_decrypt_bad_ciphertext".getBytes(UTF_8);
256 
257     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
258     assertThat(keysetResponse.getErr()).isEmpty();
259     byte[] privateKeyset = keysetResponse.getKeyset().toByteArray();
260 
261     KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset);
262     assertThat(pubResponse.getErr()).isEmpty();
263     byte[] publicKeyset = pubResponse.getPublicKeyset().toByteArray();
264 
265     assertThrows(
266         io.grpc.StatusRuntimeException.class,
267         () -> hybridDecrypt(hybridStub, publicKeyset, badCiphertext, contextInfo));
268   }
269 
270   @Test
hybridDecrypt_failsOnBadKeyset()271   public void hybridDecrypt_failsOnBadKeyset() throws Exception {
272     byte[] template = KeyTemplateProtoConverter.toByteArray(
273         EciesAeadHkdfPrivateKeyManager.eciesP256HkdfHmacSha256Aes128GcmTemplate());
274     byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
275     byte[] contextInfo = "hybrid_decrypt_bad_keyset".getBytes(UTF_8);
276 
277     KeysetGenerateResponse privateKeysetResponse = generateKeyset(keysetStub, template);
278     assertThat(privateKeysetResponse.getErr()).isEmpty();
279     byte[] privateKeyset = privateKeysetResponse.getKeyset().toByteArray();
280 
281     KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset);
282     assertThat(pubResponse.getErr()).isEmpty();
283     byte[] publicKeyset = pubResponse.getPublicKeyset().toByteArray();
284 
285     HybridEncryptResponse encResponse =
286         hybridEncrypt(hybridStub, publicKeyset, plaintext, contextInfo);
287     assertThat(encResponse.getErr()).isEmpty();
288     byte[] ciphertext = encResponse.getCiphertext().toByteArray();
289 
290     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
291     assertThrows(
292         io.grpc.StatusRuntimeException.class,
293         () -> hybridDecrypt(hybridStub, badKeyset, ciphertext, contextInfo));
294   }
295 
296   @Test
publicKeySignCreateKeyset_success()297   public void publicKeySignCreateKeyset_success() throws Exception {
298     byte[] template = KeyTemplateProtoConverter.toByteArray(
299         EcdsaSignKeyManager.ecdsaP256Template());
300     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
301     assertThat(keysetResponse.getErr()).isEmpty();
302     CreationResponse response =
303         signatureStub.createPublicKeySign(
304             CreationRequest.newBuilder()
305                 .setAnnotatedKeyset(
306                     AnnotatedKeyset.newBuilder()
307                         .setSerializedKeyset(keysetResponse.getKeyset())
308                         .build())
309                 .build());
310     assertThat(response.getErr()).isEmpty();
311   }
312 
313   @Test
publicKeySignCreateKeyset_fails()314   public void publicKeySignCreateKeyset_fails() throws Exception {
315     CreationResponse response =
316         signatureStub.createPublicKeySign(
317             CreationRequest.newBuilder()
318                 .setAnnotatedKeyset(
319                     AnnotatedKeyset.newBuilder()
320                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
321                         .build())
322                 .build());
323     assertThat(response.getErr()).isNotEmpty();
324   }
325 
326 
327   @Test
publicKeyVerifyCreateKeyset_success()328   public void publicKeyVerifyCreateKeyset_success() throws Exception {
329     byte[] template = KeyTemplateProtoConverter.toByteArray(
330         EcdsaSignKeyManager.ecdsaP256Template());
331     KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
332     assertThat(keysetResponse.getErr()).isEmpty();
333     byte[] privateKeyset = keysetResponse.getKeyset().toByteArray();
334 
335     KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset);
336     assertThat(pubResponse.getErr()).isEmpty();
337     CreationResponse response =
338         signatureStub.createPublicKeyVerify(
339             CreationRequest.newBuilder()
340                 .setAnnotatedKeyset(
341                     AnnotatedKeyset.newBuilder()
342                         .setSerializedKeyset(pubResponse.getPublicKeyset())
343                         .build())
344                 .build());
345     assertThat(response.getErr()).isEmpty();
346   }
347 
348   @Test
publicKeyVerifyCreateKeyset_fails()349   public void publicKeyVerifyCreateKeyset_fails() throws Exception {
350     CreationResponse response =
351         signatureStub.createPublicKeyVerify(
352             CreationRequest.newBuilder()
353                 .setAnnotatedKeyset(
354                     AnnotatedKeyset.newBuilder()
355                         .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))
356                         .build())
357                 .build());
358     assertThat(response.getErr()).isNotEmpty();
359   }
360 
signatureSign( SignatureGrpc.SignatureBlockingStub signatureStub, byte[] privateKeyset, byte[] data)361   private static SignatureSignResponse signatureSign(
362       SignatureGrpc.SignatureBlockingStub signatureStub, byte[] privateKeyset, byte[] data) {
363     SignatureSignRequest request =
364         SignatureSignRequest.newBuilder()
365             .setPrivateAnnotatedKeyset(
366                 AnnotatedKeyset.newBuilder()
367                     .setSerializedKeyset(ByteString.copyFrom(privateKeyset))
368                     .build())
369             .setData(ByteString.copyFrom(data))
370             .build();
371     return signatureStub.sign(request);
372   }
373 
signatureVerify( SignatureGrpc.SignatureBlockingStub signatureStub, byte[] publicKeyset, byte[] signature, byte[] data)374   private static SignatureVerifyResponse signatureVerify(
375       SignatureGrpc.SignatureBlockingStub signatureStub,
376       byte[] publicKeyset,
377       byte[] signature,
378       byte[] data) {
379     SignatureVerifyRequest request =
380         SignatureVerifyRequest.newBuilder()
381             .setPublicAnnotatedKeyset(
382                 AnnotatedKeyset.newBuilder()
383                     .setSerializedKeyset(ByteString.copyFrom(publicKeyset))
384                     .build())
385             .setSignature(ByteString.copyFrom(signature))
386             .setData(ByteString.copyFrom(data))
387             .build();
388     return signatureStub.verify(request);
389   }
390 
391   @Test
signatureSignVerify_success()392   public void signatureSignVerify_success() throws Exception {
393     byte[] template = KeyTemplateProtoConverter.toByteArray(
394         EcdsaSignKeyManager.ecdsaP256Template());
395     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
396 
397     KeysetGenerateResponse genResponse = generateKeyset(keysetStub, template);
398     assertThat(genResponse.getErr()).isEmpty();
399     byte[] privateKeyset = genResponse.getKeyset().toByteArray();
400 
401     KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset);
402     assertThat(pubResponse.getErr()).isEmpty();
403     byte[] publicKeyset = pubResponse.getPublicKeyset().toByteArray();
404 
405     SignatureSignResponse signResponse = signatureSign(signatureStub, privateKeyset, data);
406     assertThat(signResponse.getErr()).isEmpty();
407     byte[] signature = signResponse.getSignature().toByteArray();
408 
409     SignatureVerifyResponse verifyResponse =
410         signatureVerify(signatureStub, publicKeyset, signature, data);
411     assertThat(verifyResponse.getErr()).isEmpty();
412   }
413 
414   @Test
signatureSign_failsOnBadKeyset()415   public void signatureSign_failsOnBadKeyset() throws Exception {
416     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
417     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
418 
419     SignatureSignResponse response = signatureSign(signatureStub, badKeyset, data);
420     assertThat(response.getErr()).isNotEmpty();
421   }
422 
423   @Test
signatureVerify_failsOnBadSignature()424   public void signatureVerify_failsOnBadSignature() throws Exception {
425     byte[] template = KeyTemplateProtoConverter.toByteArray(
426         EcdsaSignKeyManager.ecdsaP256Template());
427     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
428 
429     KeysetGenerateResponse genResponse = generateKeyset(keysetStub, template);
430     assertThat(genResponse.getErr()).isEmpty();
431     byte[] privateKeyset = genResponse.getKeyset().toByteArray();
432 
433     KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset);
434     assertThat(pubResponse.getErr()).isEmpty();
435     byte[] publicKeyset = pubResponse.getPublicKeyset().toByteArray();
436 
437     SignatureVerifyResponse verifyResponse =
438         signatureVerify(signatureStub, publicKeyset, "bad signature".getBytes(UTF_8), data);
439     assertThat(verifyResponse.getErr()).isNotEmpty();
440   }
441 
442   @Test
signatureVerify_failsOnBadKeyset()443   public void signatureVerify_failsOnBadKeyset() throws Exception {
444     byte[] template = KeyTemplateProtoConverter.toByteArray(
445         EcdsaSignKeyManager.ecdsaP256Template());
446     byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
447 
448     KeysetGenerateResponse genResponse = generateKeyset(keysetStub, template);
449     assertThat(genResponse.getErr()).isEmpty();
450     byte[] privateKeyset = genResponse.getKeyset().toByteArray();
451 
452     SignatureSignResponse signResponse = signatureSign(signatureStub, privateKeyset, data);
453     assertThat(signResponse.getErr()).isEmpty();
454     byte[] signature = signResponse.getSignature().toByteArray();
455 
456     byte[] badKeyset = "bad keyset".getBytes(UTF_8);
457     SignatureVerifyResponse verifyResponse =
458         signatureVerify(signatureStub, badKeyset, signature, data);
459     assertThat(verifyResponse.getErr()).isNotEmpty();
460   }
461 
462 }
463