1 // Copyright 2017 Google Inc. 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; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static java.nio.charset.StandardCharsets.UTF_8; 21 22 import com.google.crypto.tink.aead.PredefinedAeadParameters; 23 import com.google.crypto.tink.config.TinkConfig; 24 import com.google.crypto.tink.mac.PredefinedMacParameters; 25 import com.google.crypto.tink.proto.Keyset; 26 import com.google.crypto.tink.subtle.Random; 27 import java.io.ByteArrayInputStream; 28 import java.io.ByteArrayOutputStream; 29 import java.security.GeneralSecurityException; 30 import org.junit.BeforeClass; 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 import org.junit.runners.JUnit4; 34 35 /** Tests for JsonKeysetWriter. */ 36 @RunWith(JUnit4.class) 37 public class JsonKeysetWriterTest { 38 @BeforeClass setUp()39 public static void setUp() throws GeneralSecurityException { 40 TinkConfig.register(); 41 } 42 assertKeysetHandle(KeysetHandle handle1, KeysetHandle handle2)43 private void assertKeysetHandle(KeysetHandle handle1, KeysetHandle handle2) throws Exception { 44 Mac mac1 = handle1.getPrimitive(RegistryConfiguration.get(), Mac.class); 45 Mac mac2 = handle2.getPrimitive(RegistryConfiguration.get(), Mac.class); 46 byte[] message = Random.randBytes(20); 47 48 assertThat(handle2.getKeyset()).isEqualTo(handle1.getKeyset()); 49 mac2.verifyMac(mac1.computeMac(message), message); 50 } 51 testWrite_shouldWork(KeysetHandle handle1)52 private void testWrite_shouldWork(KeysetHandle handle1) throws Exception { 53 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 54 CleartextKeysetHandle.write(handle1, JsonKeysetWriter.withOutputStream(outputStream)); 55 KeysetHandle handle2 = 56 CleartextKeysetHandle.read( 57 JsonKeysetReader.withInputStream(new ByteArrayInputStream(outputStream.toByteArray()))); 58 59 assertKeysetHandle(handle1, handle2); 60 } 61 62 @Test testWrite_singleKey_shouldWork()63 public void testWrite_singleKey_shouldWork() throws Exception { 64 KeysetHandle handle1 = KeysetHandle.generateNew(PredefinedMacParameters.HMAC_SHA256_128BITTAG); 65 66 testWrite_shouldWork(handle1); 67 } 68 69 @Test testWrite_multipleKeys_shouldWork()70 public void testWrite_multipleKeys_shouldWork() throws Exception { 71 KeysetHandle handle1 = 72 KeysetHandle.newBuilder() 73 .addEntry( 74 KeysetHandle.generateEntryFromParametersName("HMAC_SHA256_128BITTAG") 75 .withRandomId() 76 .makePrimary()) 77 .addEntry( 78 KeysetHandle.generateEntryFromParametersName("HMAC_SHA256_128BITTAG") 79 .withRandomId()) 80 .addEntry( 81 KeysetHandle.generateEntryFromParametersName("HMAC_SHA256_128BITTAG") 82 .withRandomId()) 83 .build(); 84 testWrite_shouldWork(handle1); 85 } 86 testWriteEncrypted_shouldWork(KeysetHandle handle1)87 private void testWriteEncrypted_shouldWork(KeysetHandle handle1) throws Exception { 88 // Encrypt the keyset with an AeadKey. 89 Aead masterKey = 90 KeysetHandle.generateNew(PredefinedAeadParameters.AES128_EAX) 91 .getPrimitive(RegistryConfiguration.get(), Aead.class); 92 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 93 handle1.write(JsonKeysetWriter.withOutputStream(outputStream), masterKey); 94 KeysetHandle handle2 = 95 KeysetHandle.read( 96 JsonKeysetReader.withInputStream(new ByteArrayInputStream(outputStream.toByteArray())), 97 masterKey); 98 99 assertKeysetHandle(handle1, handle2); 100 } 101 102 @Test testWriteEncrypted_singleKey_shouldWork()103 public void testWriteEncrypted_singleKey_shouldWork() throws Exception { 104 // Encrypt the keyset with an AeadKey. 105 KeysetHandle handle1 = KeysetHandle.generateNew(PredefinedMacParameters.HMAC_SHA256_128BITTAG); 106 107 testWriteEncrypted_shouldWork(handle1); 108 } 109 110 @Test testWriteEncrypted_multipleKeys_shouldWork()111 public void testWriteEncrypted_multipleKeys_shouldWork() throws Exception { 112 // Encrypt the keyset with an AeadKey. 113 KeysetHandle handle1 = 114 KeysetHandle.newBuilder() 115 .addEntry( 116 KeysetHandle.generateEntryFromParametersName("HMAC_SHA256_128BITTAG") 117 .withRandomId() 118 .makePrimary()) 119 .addEntry( 120 KeysetHandle.generateEntryFromParametersName("HMAC_SHA256_128BITTAG") 121 .withRandomId()) 122 .addEntry( 123 KeysetHandle.generateEntryFromParametersName("HMAC_SHA256_128BITTAG") 124 .withRandomId()) 125 .build(); 126 testWriteEncrypted_shouldWork(handle1); 127 } 128 129 @Test testWrite_writesNegativeIdAsPositive()130 public void testWrite_writesNegativeIdAsPositive() throws Exception { 131 int magicKeyId = -19230912; 132 Keyset unmodified = 133 CleartextKeysetHandle.getKeyset( 134 KeysetHandle.generateNew(PredefinedMacParameters.HMAC_SHA256_128BITTAG)); 135 Keyset modified = 136 Keyset.newBuilder(unmodified) 137 .setPrimaryKeyId(magicKeyId) 138 .setKey(0, Keyset.Key.newBuilder(unmodified.getKey(0)).setKeyId(magicKeyId).build()) 139 .build(); 140 KeysetHandle modifiedHandle = 141 TinkProtoKeysetFormat.parseKeyset(modified.toByteArray(), InsecureSecretKeyAccess.get()); 142 143 // Write cleartext keyset 144 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 145 CleartextKeysetHandle.write(modifiedHandle, JsonKeysetWriter.withOutputStream(outputStream)); 146 String cleartextKeysetInJson = new String(outputStream.toByteArray(), UTF_8); 147 148 assertThat(cleartextKeysetInJson).contains("\"primaryKeyId\":4275736384"); 149 assertThat(cleartextKeysetInJson).contains("\"keyId\":4275736384"); 150 151 // Write encrypted keyset 152 Aead keysetEncryptionAead = 153 KeysetHandle.generateNew(KeyTemplates.get("AES128_EAX")) 154 .getPrimitive(RegistryConfiguration.get(), Aead.class); 155 ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream(); 156 modifiedHandle.write(JsonKeysetWriter.withOutputStream(outputStream2), keysetEncryptionAead); 157 String encryptedKeysetInJson = new String(outputStream2.toByteArray(), UTF_8); 158 159 assertThat(encryptedKeysetInJson).contains("\"primaryKeyId\":4275736384"); 160 assertThat(encryptedKeysetInJson).contains("\"keyId\":4275736384"); 161 } 162 163 } 164