blob: 76eb754c863e37a2db0947c106c72b73617af7fe [file] [log] [blame]
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package com.google.crypto.tink.testing;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.crypto.tink.BinaryKeysetReader;
import com.google.crypto.tink.KeyTemplate;
import com.google.crypto.tink.KeyTemplates;
import com.google.crypto.tink.config.TinkConfig;
import com.google.crypto.tink.daead.AesSivKeyManager;
import com.google.crypto.tink.internal.KeyTemplateProtoConverter;
import com.google.crypto.tink.mac.HmacKeyManager;
import com.google.crypto.tink.prf.HmacPrfKeyManager;
import com.google.crypto.tink.proto.Keyset;
import com.google.crypto.tink.streamingaead.AesGcmHkdfStreamingKeyManager;
import com.google.crypto.tink.testing.proto.AeadDecryptRequest;
import com.google.crypto.tink.testing.proto.AeadDecryptResponse;
import com.google.crypto.tink.testing.proto.AeadEncryptRequest;
import com.google.crypto.tink.testing.proto.AeadEncryptResponse;
import com.google.crypto.tink.testing.proto.AeadGrpc;
import com.google.crypto.tink.testing.proto.BytesValue;
import com.google.crypto.tink.testing.proto.ComputeMacRequest;
import com.google.crypto.tink.testing.proto.ComputeMacResponse;
import com.google.crypto.tink.testing.proto.DeterministicAeadDecryptRequest;
import com.google.crypto.tink.testing.proto.DeterministicAeadDecryptResponse;
import com.google.crypto.tink.testing.proto.DeterministicAeadEncryptRequest;
import com.google.crypto.tink.testing.proto.DeterministicAeadEncryptResponse;
import com.google.crypto.tink.testing.proto.DeterministicAeadGrpc;
import com.google.crypto.tink.testing.proto.KeysetFromJsonRequest;
import com.google.crypto.tink.testing.proto.KeysetFromJsonResponse;
import com.google.crypto.tink.testing.proto.KeysetGenerateRequest;
import com.google.crypto.tink.testing.proto.KeysetGenerateResponse;
import com.google.crypto.tink.testing.proto.KeysetGrpc;
import com.google.crypto.tink.testing.proto.KeysetReadEncryptedRequest;
import com.google.crypto.tink.testing.proto.KeysetReadEncryptedResponse;
import com.google.crypto.tink.testing.proto.KeysetReaderType;
import com.google.crypto.tink.testing.proto.KeysetTemplateRequest;
import com.google.crypto.tink.testing.proto.KeysetTemplateResponse;
import com.google.crypto.tink.testing.proto.KeysetToJsonRequest;
import com.google.crypto.tink.testing.proto.KeysetToJsonResponse;
import com.google.crypto.tink.testing.proto.KeysetWriteEncryptedRequest;
import com.google.crypto.tink.testing.proto.KeysetWriteEncryptedResponse;
import com.google.crypto.tink.testing.proto.KeysetWriterType;
import com.google.crypto.tink.testing.proto.MacGrpc;
import com.google.crypto.tink.testing.proto.MetadataGrpc;
import com.google.crypto.tink.testing.proto.PrfSetComputeRequest;
import com.google.crypto.tink.testing.proto.PrfSetComputeResponse;
import com.google.crypto.tink.testing.proto.PrfSetGrpc;
import com.google.crypto.tink.testing.proto.PrfSetKeyIdsRequest;
import com.google.crypto.tink.testing.proto.PrfSetKeyIdsResponse;
import com.google.crypto.tink.testing.proto.ServerInfoRequest;
import com.google.crypto.tink.testing.proto.ServerInfoResponse;
import com.google.crypto.tink.testing.proto.StreamingAeadDecryptRequest;
import com.google.crypto.tink.testing.proto.StreamingAeadDecryptResponse;
import com.google.crypto.tink.testing.proto.StreamingAeadEncryptRequest;
import com.google.crypto.tink.testing.proto.StreamingAeadEncryptResponse;
import com.google.crypto.tink.testing.proto.StreamingAeadGrpc;
import com.google.crypto.tink.testing.proto.VerifyMacRequest;
import com.google.crypto.tink.testing.proto.VerifyMacResponse;
import com.google.protobuf.ByteString;
import io.grpc.ManagedChannel;
import io.grpc.Server;
import io.grpc.inprocess.InProcessChannelBuilder;
import io.grpc.inprocess.InProcessServerBuilder;
import java.util.Optional;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class TestingServicesTest {
private Server server;
private ManagedChannel channel;
MetadataGrpc.MetadataBlockingStub metadataStub;
KeysetGrpc.KeysetBlockingStub keysetStub;
AeadGrpc.AeadBlockingStub aeadStub;
DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub;
StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub;
MacGrpc.MacBlockingStub macStub;
PrfSetGrpc.PrfSetBlockingStub prfSetStub;
@Before
public void setUp() throws Exception {
TinkConfig.register();
String serverName = InProcessServerBuilder.generateName();
server = InProcessServerBuilder
.forName(serverName)
.directExecutor()
.addService(new MetadataServiceImpl())
.addService(new KeysetServiceImpl())
.addService(new AeadServiceImpl())
.addService(new DeterministicAeadServiceImpl())
.addService(new StreamingAeadServiceImpl())
.addService(new MacServiceImpl())
.addService(new PrfSetServiceImpl())
.build()
.start();
channel = InProcessChannelBuilder
.forName(serverName)
.directExecutor()
.build();
metadataStub = MetadataGrpc.newBlockingStub(channel);
keysetStub = KeysetGrpc.newBlockingStub(channel);
aeadStub = AeadGrpc.newBlockingStub(channel);
daeadStub = DeterministicAeadGrpc.newBlockingStub(channel);
streamingAeadStub = StreamingAeadGrpc.newBlockingStub(channel);
macStub = MacGrpc.newBlockingStub(channel);
prfSetStub = PrfSetGrpc.newBlockingStub(channel);
}
@After
public void tearDown() throws Exception {
assertThat(channel.shutdown().awaitTermination(5, SECONDS)).isTrue();
assertThat(server.shutdown().awaitTermination(5, SECONDS)).isTrue();
}
private static KeysetGenerateResponse generateKeyset(
KeysetGrpc.KeysetBlockingStub keysetStub, byte[] template) {
KeysetGenerateRequest genRequest =
KeysetGenerateRequest.newBuilder().setTemplate(ByteString.copyFrom(template)).build();
return keysetStub.generate(genRequest);
}
private static KeysetToJsonResponse keysetToJson(
KeysetGrpc.KeysetBlockingStub keysetStub, byte[] keyset) {
KeysetToJsonRequest request =
KeysetToJsonRequest.newBuilder().setKeyset(ByteString.copyFrom(keyset)).build();
return keysetStub.toJson(request);
}
private static KeysetFromJsonResponse keysetFromJson(
KeysetGrpc.KeysetBlockingStub keysetStub, String jsonKeyset) {
KeysetFromJsonRequest request =
KeysetFromJsonRequest.newBuilder().setJsonKeyset(jsonKeyset).build();
return keysetStub.fromJson(request);
}
@Test
public void template_success() throws Exception {
KeysetTemplateRequest request =
KeysetTemplateRequest.newBuilder().setTemplateName("AES256_GCM").build();
KeysetTemplateResponse response = keysetStub.getTemplate(request);
assertThat(response.getErr()).isEmpty();
KeyTemplate template =
KeyTemplateProtoConverter.fromByteArray(response.getKeyTemplate().toByteArray());
assertThat(template.getTypeUrl()).isEqualTo("type.googleapis.com/google.crypto.tink.AesGcmKey");
}
@Test
public void template_not_found() throws Exception {
KeysetTemplateRequest request =
KeysetTemplateRequest.newBuilder().setTemplateName("UNKNOWN_TEMPLATE").build();
KeysetTemplateResponse response = keysetStub.getTemplate(request);
assertThat(response.getErr()).isNotEmpty();
}
@Test
public void toJson_success() throws Exception {
String jsonKeyset =
""
+ "{"
+ " \"primaryKeyId\": 42,"
+ " \"key\": ["
+ " {"
+ " \"keyData\": {"
+ " \"typeUrl\": \"type.googleapis.com/google.crypto.tink.AesGcmKey\","
+ " \"keyMaterialType\": \"SYMMETRIC\","
+ " \"value\": \"AFakeTestKeyValue1234567\""
+ " },"
+ " \"outputPrefixType\": \"TINK\","
+ " \"keyId\": 42,"
+ " \"status\": \"ENABLED\""
+ " }"
+ " ]"
+ "}";
KeysetFromJsonResponse fromResponse = keysetFromJson(keysetStub, jsonKeyset);
assertThat(fromResponse.getErr()).isEmpty();
byte[] output = fromResponse.getKeyset().toByteArray();
Keyset keyset = BinaryKeysetReader.withBytes(output).read();
assertThat(keyset.getPrimaryKeyId()).isEqualTo(42);
}
@Test
public void toFromJson_success() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
KeysetToJsonResponse toResponse = keysetToJson(keysetStub, keyset);
assertThat(toResponse.getErr()).isEmpty();
String jsonKeyset = toResponse.getJsonKeyset();
KeysetFromJsonResponse fromResponse = keysetFromJson(keysetStub, jsonKeyset);
assertThat(fromResponse.getErr()).isEmpty();
byte[] output = fromResponse.getKeyset().toByteArray();
assertThat(output).isEqualTo(keyset);
}
private static KeysetReadEncryptedResponse keysetReadEncrypted(
KeysetGrpc.KeysetBlockingStub keysetStub,
byte[] encryptedKeyset,
byte[] masterKeyset,
Optional<byte[]> associatedData) {
KeysetReadEncryptedRequest.Builder requestBuilder =
KeysetReadEncryptedRequest.newBuilder()
.setEncryptedKeyset(ByteString.copyFrom(encryptedKeyset))
.setMasterKeyset(ByteString.copyFrom(masterKeyset))
.setKeysetReaderType(KeysetReaderType.KEYSET_READER_BINARY);
if (associatedData.isPresent()) {
requestBuilder.setAssociatedData(
BytesValue.newBuilder().setValue(ByteString.copyFrom(associatedData.get())).build());
}
return keysetStub.readEncrypted(requestBuilder.build());
}
private static KeysetWriteEncryptedResponse keysetWriteEncrypted(
KeysetGrpc.KeysetBlockingStub keysetStub, byte[] keyset, byte[] masterKeyset,
Optional<byte[]> associatedData) {
KeysetWriteEncryptedRequest.Builder requestBuilder =
KeysetWriteEncryptedRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setMasterKeyset(ByteString.copyFrom(masterKeyset))
.setKeysetWriterType(KeysetWriterType.KEYSET_WRITER_BINARY);
if (associatedData.isPresent()) {
requestBuilder.setAssociatedData(
BytesValue.newBuilder().setValue(ByteString.copyFrom(associatedData.get())).build());
}
return keysetStub.writeEncrypted(requestBuilder.build());
}
@Test
public void generateEncryptDecryptKeyset() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
KeysetGenerateResponse masterKeysetResponse = generateKeyset(keysetStub, template);
assertThat(masterKeysetResponse.getErr()).isEmpty();
byte[] masterKeyset = masterKeysetResponse.getKeyset().toByteArray();
KeysetWriteEncryptedResponse writeResponse =
keysetWriteEncrypted(keysetStub, keyset, masterKeyset, /*associatedData=*/Optional.empty());
assertThat(writeResponse.getErr()).isEmpty();
byte[] encryptedKeyset = writeResponse.getEncryptedKeyset().toByteArray();
assertThat(encryptedKeyset).isNotEqualTo(keyset);
KeysetReadEncryptedResponse readResponse =
keysetReadEncrypted(
keysetStub, encryptedKeyset, masterKeyset, /*associatedData=*/ Optional.empty());
assertThat(readResponse.getErr()).isEmpty();
byte[] output = readResponse.getKeyset().toByteArray();
assertThat(output).isEqualTo(keyset);
}
@Test
public void generateEncryptDecryptKeysetWithAssociatedData() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
byte[] associatedData = "a".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
KeysetGenerateResponse masterKeysetResponse = generateKeyset(keysetStub, template);
assertThat(masterKeysetResponse.getErr()).isEmpty();
byte[] masterKeyset = masterKeysetResponse.getKeyset().toByteArray();
KeysetWriteEncryptedResponse writeResponse =
keysetWriteEncrypted(keysetStub, keyset, masterKeyset, Optional.of(associatedData));
assertThat(writeResponse.getErr()).isEmpty();
byte[] encryptedKeyset = writeResponse.getEncryptedKeyset().toByteArray();
assertThat(encryptedKeyset).isNotEqualTo(keyset);
KeysetReadEncryptedResponse readResponse =
keysetReadEncrypted(
keysetStub, encryptedKeyset, masterKeyset, Optional.of(associatedData));
assertThat(readResponse.getErr()).isEmpty();
byte[] output = readResponse.getKeyset().toByteArray();
assertThat(output).isEqualTo(keyset);
}
@Test
public void encryptDecryptInvalidKeyset_fails() throws Exception {
byte[] invalidData = "invalid".getBytes(UTF_8);
byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
KeysetGenerateResponse masterKeysetResponse = generateKeyset(keysetStub, template);
assertThat(masterKeysetResponse.getErr()).isEmpty();
byte[] masterKeyset = masterKeysetResponse.getKeyset().toByteArray();
KeysetWriteEncryptedResponse writeResponse1 =
keysetWriteEncrypted(keysetStub, keyset, invalidData, /*associatedData=*/ Optional.empty());
assertThat(writeResponse1.getErr()).isNotEmpty();
KeysetWriteEncryptedResponse writeResponse2 =
keysetWriteEncrypted(
keysetStub, invalidData, masterKeyset, /*associatedData=*/ Optional.empty());
assertThat(writeResponse2.getErr()).isNotEmpty();
KeysetReadEncryptedResponse readResponse1 =
keysetReadEncrypted(keysetStub, keyset, invalidData, /*associatedData=*/ Optional.empty());
assertThat(readResponse1.getErr()).isNotEmpty();
KeysetReadEncryptedResponse readResponse2 =
keysetReadEncrypted(
keysetStub, invalidData, masterKeyset, /*associatedData=*/ Optional.empty());
assertThat(readResponse2.getErr()).isNotEmpty();
}
private static AeadEncryptResponse aeadEncrypt(
AeadGrpc.AeadBlockingStub aeadStub, byte[] keyset, byte[] plaintext, byte[] associatedData) {
AeadEncryptRequest encRequest =
AeadEncryptRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setPlaintext(ByteString.copyFrom(plaintext))
.setAssociatedData(ByteString.copyFrom(associatedData))
.build();
return aeadStub.encrypt(encRequest);
}
private static AeadDecryptResponse aeadDecrypt(
AeadGrpc.AeadBlockingStub aeadStub, byte[] keyset, byte[] ciphertext, byte[] associatedData) {
AeadDecryptRequest decRequest =
AeadDecryptRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setCiphertext(ByteString.copyFrom(ciphertext))
.setAssociatedData(ByteString.copyFrom(associatedData))
.build();
return aeadStub.decrypt(decRequest);
}
@Test
public void aeadGenerateEncryptDecrypt_success() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
AeadEncryptResponse encResponse = aeadEncrypt(aeadStub, keyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isEmpty();
byte[] ciphertext = encResponse.getCiphertext().toByteArray();
AeadDecryptResponse decResponse = aeadDecrypt(aeadStub, keyset, ciphertext, associatedData);
assertThat(decResponse.getErr()).isEmpty();
byte[] output = decResponse.getPlaintext().toByteArray();
assertThat(output).isEqualTo(plaintext);
}
@Test
public void generateKeyset_failsOnBadTemplate() throws Exception {
byte[] badTemplate = "bad template".getBytes(UTF_8);
KeysetGenerateResponse genResponse = generateKeyset(keysetStub, badTemplate);
assertThat(genResponse.getErr()).isNotEmpty();
}
@Test
public void aeadEncrypt_failsOnBadKeyset() throws Exception {
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "aead_encrypt_fails_on_bad_keyset".getBytes(UTF_8);
AeadEncryptResponse encResponse = aeadEncrypt(aeadStub, badKeyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isNotEmpty();
}
@Test
public void aeadDecrypt_failsOnBadCiphertext() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
byte[] badCiphertext = "bad ciphertext".getBytes(UTF_8);
byte[] associatedData = "aead_decrypt_fails_on_bad_ciphertext".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
AeadDecryptResponse decResponse = aeadDecrypt(aeadStub, keyset, badCiphertext, associatedData);
assertThat(decResponse.getErr()).isNotEmpty();
}
@Test
public void aeadDecrypt_failsOnBadKeyset() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("AES128_GCM"));
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
AeadEncryptResponse encResponse = aeadEncrypt(aeadStub, keyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isEmpty();
byte[] ciphertext = encResponse.getCiphertext().toByteArray();
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
AeadDecryptResponse decResponse = aeadDecrypt(aeadStub, badKeyset, ciphertext, associatedData);
assertThat(decResponse.getErr()).isNotEmpty();
}
private static DeterministicAeadEncryptResponse daeadEncrypt(
DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub,
byte[] keyset,
byte[] plaintext,
byte[] associatedData) {
DeterministicAeadEncryptRequest encRequest =
DeterministicAeadEncryptRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setPlaintext(ByteString.copyFrom(plaintext))
.setAssociatedData(ByteString.copyFrom(associatedData))
.build();
return daeadStub.encryptDeterministically(encRequest);
}
private static DeterministicAeadDecryptResponse daeadDecrypt(
DeterministicAeadGrpc.DeterministicAeadBlockingStub daeadStub,
byte[] keyset,
byte[] ciphertext,
byte[] associatedData) {
DeterministicAeadDecryptRequest decRequest =
DeterministicAeadDecryptRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setCiphertext(ByteString.copyFrom(ciphertext))
.setAssociatedData(ByteString.copyFrom(associatedData))
.build();
return daeadStub.decryptDeterministically(decRequest);
}
@Test
public void daeadGenerateEncryptDecryptDeterministically_success() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(AesSivKeyManager.aes256SivTemplate());
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
DeterministicAeadEncryptResponse encResponse =
daeadEncrypt(daeadStub, keyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isEmpty();
byte[] ciphertext = encResponse.getCiphertext().toByteArray();
DeterministicAeadDecryptResponse decResponse =
daeadDecrypt(daeadStub, keyset, ciphertext, associatedData);
assertThat(decResponse.getErr()).isEmpty();
byte[] output = decResponse.getPlaintext().toByteArray();
assertThat(output).isEqualTo(plaintext);
}
@Test
public void daeadEncryptDeterministically_failsOnBadKeyset() throws Exception {
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "aead_encrypt_fails_on_bad_keyset".getBytes(UTF_8);
DeterministicAeadEncryptResponse encResponse =
daeadEncrypt(daeadStub, badKeyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isNotEmpty();
}
@Test
public void daeadDecryptDeterministically_failsOnBadCiphertext() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(AesSivKeyManager.aes256SivTemplate());
byte[] badCiphertext = "bad ciphertext".getBytes(UTF_8);
byte[] associatedData = "aead_decrypt_fails_on_bad_ciphertext".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
DeterministicAeadDecryptResponse decResponse =
daeadDecrypt(daeadStub, keyset, badCiphertext, associatedData);
assertThat(decResponse.getErr()).isNotEmpty();
}
@Test
public void daeadDecryptDeterministically_failsOnBadKeyset() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(AesSivKeyManager.aes256SivTemplate());
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
DeterministicAeadEncryptResponse encResponse =
daeadEncrypt(daeadStub, keyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isEmpty();
byte[] ciphertext = encResponse.getCiphertext().toByteArray();
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
DeterministicAeadDecryptResponse decResponse =
daeadDecrypt(daeadStub, badKeyset, ciphertext, associatedData);
assertThat(decResponse.getErr()).isNotEmpty();
}
private static StreamingAeadEncryptResponse streamingAeadEncrypt(
StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub,
byte[] keyset,
byte[] plaintext,
byte[] associatedData) {
StreamingAeadEncryptRequest encRequest =
StreamingAeadEncryptRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setPlaintext(ByteString.copyFrom(plaintext))
.setAssociatedData(ByteString.copyFrom(associatedData))
.build();
return streamingAeadStub.encrypt(encRequest);
}
private static StreamingAeadDecryptResponse streamingAeadDecrypt(
StreamingAeadGrpc.StreamingAeadBlockingStub streamingAeadStub,
byte[] keyset,
byte[] ciphertext,
byte[] associatedData) {
StreamingAeadDecryptRequest decRequest =
StreamingAeadDecryptRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setCiphertext(ByteString.copyFrom(ciphertext))
.setAssociatedData(ByteString.copyFrom(associatedData))
.build();
return streamingAeadStub.decrypt(decRequest);
}
@Test
public void streamingAeadGenerateEncryptDecrypt_success() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
AesGcmHkdfStreamingKeyManager.aes128GcmHkdf4KBTemplate());
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
StreamingAeadEncryptResponse encResponse = streamingAeadEncrypt(
streamingAeadStub, keyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isEmpty();
byte[] ciphertext = encResponse.getCiphertext().toByteArray();
StreamingAeadDecryptResponse decResponse = streamingAeadDecrypt(
streamingAeadStub, keyset, ciphertext, associatedData);
assertThat(decResponse.getErr()).isEmpty();
byte[] output = decResponse.getPlaintext().toByteArray();
assertThat(output).isEqualTo(plaintext);
}
@Test
public void streamingAeadEncrypt_failsOnBadKeyset() throws Exception {
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "streamingAead_encrypt_fails_on_bad_keyset".getBytes(UTF_8);
StreamingAeadEncryptResponse encResponse = streamingAeadEncrypt(
streamingAeadStub, badKeyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isNotEmpty();
}
@Test
public void streamingAeadDecrypt_failsOnBadCiphertext() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
AesGcmHkdfStreamingKeyManager.aes128GcmHkdf4KBTemplate());
byte[] badCiphertext = "bad ciphertext".getBytes(UTF_8);
byte[] associatedData = "streamingAead_decrypt_fails_on_bad_ciphertext".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
StreamingAeadDecryptResponse decResponse = streamingAeadDecrypt(
streamingAeadStub, keyset, badCiphertext, associatedData);
assertThat(decResponse.getErr()).isNotEmpty();
}
@Test
public void streamingAeadDecrypt_failsOnBadKeyset() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
AesGcmHkdfStreamingKeyManager.aes128GcmHkdf4KBTemplate());
byte[] plaintext = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
byte[] associatedData = "generate_encrypt_decrypt".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
StreamingAeadEncryptResponse encResponse = streamingAeadEncrypt(
streamingAeadStub, keyset, plaintext, associatedData);
assertThat(encResponse.getErr()).isEmpty();
byte[] ciphertext = encResponse.getCiphertext().toByteArray();
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
StreamingAeadDecryptResponse decResponse = streamingAeadDecrypt(
streamingAeadStub, badKeyset, ciphertext, associatedData);
assertThat(decResponse.getErr()).isNotEmpty();
}
private static ComputeMacResponse computeMac(
MacGrpc.MacBlockingStub macStub, byte[] keyset, byte[] data) {
ComputeMacRequest request =
ComputeMacRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setData(ByteString.copyFrom(data))
.build();
return macStub.computeMac(request);
}
private static VerifyMacResponse verifyMac(
MacGrpc.MacBlockingStub macStub, byte[] keyset, byte[] macValue, byte[] data) {
VerifyMacRequest request =
VerifyMacRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setMacValue(ByteString.copyFrom(macValue))
.setData(ByteString.copyFrom(data))
.build();
return macStub.verifyMac(request);
}
@Test
public void computeVerifyMac_success() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
HmacKeyManager.hmacSha256HalfDigestTemplate());
byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
ComputeMacResponse compResponse = computeMac(macStub, keyset, data);
assertThat(compResponse.getErr()).isEmpty();
byte[] macValue = compResponse.getMacValue().toByteArray();
VerifyMacResponse verifyResponse = verifyMac(macStub, keyset, macValue, data);
assertThat(verifyResponse.getErr()).isEmpty();
}
@Test
public void computeMac_failsOnBadKeyset() throws Exception {
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
ComputeMacResponse compResponse = computeMac(macStub, badKeyset, data);
assertThat(compResponse.getErr()).isNotEmpty();
}
@Test
public void verifyMac_failsOnBadMacValue() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
HmacKeyManager.hmacSha256HalfDigestTemplate());
byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
VerifyMacResponse verifyResponse =
verifyMac(macStub, keyset, "bad mac_value".getBytes(UTF_8), data);
assertThat(verifyResponse.getErr()).isNotEmpty();
}
@Test
public void verifyMac_failsOnBadKeyset() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
HmacKeyManager.hmacSha256HalfDigestTemplate());
byte[] data = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
ComputeMacResponse compResponse = computeMac(macStub, keyset, data);
assertThat(compResponse.getErr()).isEmpty();
byte[] macValue = compResponse.getMacValue().toByteArray();
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
VerifyMacResponse verifyResponse = verifyMac(macStub, badKeyset, macValue, data);
assertThat(verifyResponse.getErr()).isNotEmpty();
}
private static PrfSetKeyIdsResponse keyIds(
PrfSetGrpc.PrfSetBlockingStub prfSetStub, byte[] keyset) {
PrfSetKeyIdsRequest request =
PrfSetKeyIdsRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.build();
return prfSetStub.keyIds(request);
}
private static PrfSetComputeResponse computePrf(
PrfSetGrpc.PrfSetBlockingStub prfSetStub,
byte[] keyset,
int keyId,
byte[] inputData,
int outputLength) {
PrfSetComputeRequest request =
PrfSetComputeRequest.newBuilder()
.setKeyset(ByteString.copyFrom(keyset))
.setKeyId(keyId)
.setInputData(ByteString.copyFrom(inputData))
.setOutputLength(outputLength)
.build();
return prfSetStub.compute(request);
}
@Test
public void computePrf_success() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
HmacPrfKeyManager.hmacSha256Template());
byte[] inputData = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
int outputLength = 15;
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
PrfSetKeyIdsResponse keyIdsResponse = keyIds(prfSetStub, keyset);
assertThat(keyIdsResponse.getErr()).isEmpty();
int primaryKeyId = keyIdsResponse.getOutput().getPrimaryKeyId();
PrfSetComputeResponse computeResponse = computePrf(
prfSetStub, keyset, primaryKeyId, inputData, outputLength);
assertThat(computeResponse.getErr()).isEmpty();
assertThat(computeResponse.getOutput().size()).isEqualTo(outputLength);
}
@Test
public void prfKeyIds_failsOnBadKeyset() throws Exception {
byte[] badKeyset = "bad keyset".getBytes(UTF_8);
PrfSetKeyIdsResponse keyIdsResponse = keyIds(prfSetStub, badKeyset);
assertThat(keyIdsResponse.getErr()).isNotEmpty();
}
@Test
public void computePrf_failsOnUnknownKeyId() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
HmacPrfKeyManager.hmacSha256Template());
byte[] inputData = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
int outputLength = 15;
int badKeyId = 123456789;
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
PrfSetComputeResponse computeResponse = computePrf(
prfSetStub, keyset, badKeyId, inputData, outputLength);
assertThat(computeResponse.getErr()).isNotEmpty();
}
@Test
public void computePrf_failsOnBadOutputLength() throws Exception {
byte[] template = KeyTemplateProtoConverter.toByteArray(
HmacPrfKeyManager.hmacSha256Template());
byte[] inputData = "The quick brown fox jumps over the lazy dog".getBytes(UTF_8);
int outputLength = 12345;
KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template);
assertThat(keysetResponse.getErr()).isEmpty();
byte[] keyset = keysetResponse.getKeyset().toByteArray();
PrfSetKeyIdsResponse keyIdsResponse = keyIds(prfSetStub, keyset);
assertThat(keyIdsResponse.getErr()).isEmpty();
int primaryKeyId = keyIdsResponse.getOutput().getPrimaryKeyId();
PrfSetComputeResponse computeResponse = computePrf(
prfSetStub, keyset, primaryKeyId, inputData, outputLength);
assertThat(computeResponse.getErr()).isNotEmpty();
}
@Test
public void getServerInfo_success() throws Exception {
ServerInfoResponse response =
metadataStub.getServerInfo(ServerInfoRequest.getDefaultInstance());
assertThat(response.getLanguage()).isEqualTo("java");
assertThat(response.getTinkVersion()).isNotEmpty();
}
}