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.streamingaead; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 22 import com.google.crypto.tink.InsecureSecretKeyAccess; 23 import com.google.crypto.tink.KeysetHandle; 24 import com.google.crypto.tink.RegistryConfiguration; 25 import com.google.crypto.tink.StreamingAead; 26 import com.google.crypto.tink.TinkProtoKeysetFormat; 27 import com.google.crypto.tink.internal.PrimitiveRegistry; 28 import com.google.crypto.tink.proto.HashType; 29 import com.google.crypto.tink.proto.KeyData; 30 import com.google.crypto.tink.proto.KeyData.KeyMaterialType; 31 import com.google.crypto.tink.proto.KeyStatusType; 32 import com.google.crypto.tink.proto.Keyset; 33 import com.google.crypto.tink.proto.OutputPrefixType; 34 import com.google.crypto.tink.subtle.Hex; 35 import com.google.crypto.tink.testing.StreamingTestUtil; 36 import com.google.crypto.tink.util.SecretBytes; 37 import com.google.protobuf.ByteString; 38 import java.io.IOException; 39 import java.security.GeneralSecurityException; 40 import org.junit.BeforeClass; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.junit.runners.JUnit4; 44 45 /** Tests for StreamingAeadWrapper. */ 46 @RunWith(JUnit4.class) 47 // Fully specifying proto key/parameters types to distinguish from the programmatic ones. 48 @SuppressWarnings("UnnecessarilyFullyQualified") 49 public class StreamingAeadWrapperTest { 50 private static final String AES_GCM_HKDF_TYPE_URL = 51 "type.googleapis.com/google.crypto.tink.AesGcmHkdfStreamingKey"; 52 53 @BeforeClass setUp()54 public static void setUp() throws Exception { 55 StreamingAeadConfig.register(); 56 } 57 58 @Test encryptDecrypt_works()59 public void encryptDecrypt_works() throws Exception { 60 AesCtrHmacStreamingParameters parameters = 61 AesCtrHmacStreamingParameters.builder() 62 .setKeySizeBytes(32) 63 .setDerivedKeySizeBytes(32) 64 .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 65 .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 66 .setHmacTagSizeBytes(16) 67 .setCiphertextSegmentSizeBytes(64) 68 .build(); 69 AesCtrHmacStreamingKey key = 70 AesCtrHmacStreamingKey.create( 71 parameters, 72 SecretBytes.copyFrom( 73 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"), 74 InsecureSecretKeyAccess.get())); 75 KeysetHandle keysetHandle = 76 KeysetHandle.newBuilder() 77 .addEntry(KeysetHandle.importKey(key).withFixedId(42).makePrimary()) 78 .build(); 79 80 StreamingAead streamingAead = 81 keysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 82 83 StreamingTestUtil.testEncryptDecrypt(streamingAead, 0, 20, 5); 84 } 85 86 @Test encryptDecrypt_usesPrimary()87 public void encryptDecrypt_usesPrimary() throws Exception { 88 AesGcmHkdfStreamingParameters aesGcmHkdfStreamingParameters = 89 AesGcmHkdfStreamingParameters.builder() 90 .setKeySizeBytes(32) 91 .setDerivedAesGcmKeySizeBytes(32) 92 .setHkdfHashType(AesGcmHkdfStreamingParameters.HashType.SHA256) 93 .setCiphertextSegmentSizeBytes(64) 94 .build(); 95 AesGcmHkdfStreamingKey aesGcmHkdfStreamingKey = 96 AesGcmHkdfStreamingKey.create( 97 aesGcmHkdfStreamingParameters, 98 SecretBytes.copyFrom( 99 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"), 100 InsecureSecretKeyAccess.get())); 101 AesCtrHmacStreamingParameters aesCtrHmacStreamingParameters = 102 AesCtrHmacStreamingParameters.builder() 103 .setKeySizeBytes(32) 104 .setDerivedKeySizeBytes(32) 105 .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 106 .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 107 .setHmacTagSizeBytes(16) 108 .setCiphertextSegmentSizeBytes(64) 109 .build(); 110 AesCtrHmacStreamingKey aesCtrHmacStreamingKey = 111 AesCtrHmacStreamingKey.create( 112 aesCtrHmacStreamingParameters, 113 SecretBytes.copyFrom( 114 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"), 115 InsecureSecretKeyAccess.get())); 116 KeysetHandle fullKeysetHandle = 117 KeysetHandle.newBuilder() 118 .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43)) 119 .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary()) 120 .build(); 121 KeysetHandle onlyPrimaryKeysetHandle = 122 KeysetHandle.newBuilder() 123 .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary()) 124 .build(); 125 126 StreamingAead fullStreamingAead = 127 fullKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 128 StreamingAead onlyPrimaryStreamingAead = 129 onlyPrimaryKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 130 131 StreamingTestUtil.testEncryptDecryptDifferentInstances( 132 fullStreamingAead, onlyPrimaryStreamingAead, 0, 20, 5); 133 StreamingTestUtil.testEncryptDecryptDifferentInstances( 134 onlyPrimaryStreamingAead, fullStreamingAead, 0, 20, 5); 135 } 136 137 @Test encryptDecrypt_shiftedPrimaryWorks()138 public void encryptDecrypt_shiftedPrimaryWorks() throws Exception { 139 AesGcmHkdfStreamingParameters aesGcmHkdfStreamingParameters = 140 AesGcmHkdfStreamingParameters.builder() 141 .setKeySizeBytes(32) 142 .setDerivedAesGcmKeySizeBytes(32) 143 .setHkdfHashType(AesGcmHkdfStreamingParameters.HashType.SHA256) 144 .setCiphertextSegmentSizeBytes(64) 145 .build(); 146 AesGcmHkdfStreamingKey aesGcmHkdfStreamingKey = 147 AesGcmHkdfStreamingKey.create( 148 aesGcmHkdfStreamingParameters, 149 SecretBytes.copyFrom( 150 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"), 151 InsecureSecretKeyAccess.get())); 152 AesCtrHmacStreamingParameters aesCtrHmacStreamingParameters = 153 AesCtrHmacStreamingParameters.builder() 154 .setKeySizeBytes(32) 155 .setDerivedKeySizeBytes(32) 156 .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 157 .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 158 .setHmacTagSizeBytes(16) 159 .setCiphertextSegmentSizeBytes(64) 160 .build(); 161 AesCtrHmacStreamingKey aesCtrHmacStreamingKey = 162 AesCtrHmacStreamingKey.create( 163 aesCtrHmacStreamingParameters, 164 SecretBytes.copyFrom( 165 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"), 166 InsecureSecretKeyAccess.get())); 167 KeysetHandle keysetHandle = 168 KeysetHandle.newBuilder() 169 .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43)) 170 .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary()) 171 .build(); 172 KeysetHandle shiftedPrimaryKeysetHandle = 173 KeysetHandle.newBuilder() 174 .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43).makePrimary()) 175 .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42)) 176 .build(); 177 178 StreamingAead streamingAead = 179 keysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 180 StreamingAead shiftedPrimaryStreamingAead = 181 shiftedPrimaryKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 182 183 StreamingTestUtil.testEncryptDecryptDifferentInstances( 184 streamingAead, shiftedPrimaryStreamingAead, 0, 20, 5); 185 StreamingTestUtil.testEncryptDecryptDifferentInstances( 186 shiftedPrimaryStreamingAead, streamingAead, 0, 20, 5); 187 } 188 189 @Test wrongKey_throws()190 public void wrongKey_throws() throws Exception { 191 AesGcmHkdfStreamingParameters aesGcmHkdfStreamingParameters = 192 AesGcmHkdfStreamingParameters.builder() 193 .setKeySizeBytes(32) 194 .setDerivedAesGcmKeySizeBytes(32) 195 .setHkdfHashType(AesGcmHkdfStreamingParameters.HashType.SHA256) 196 .setCiphertextSegmentSizeBytes(64) 197 .build(); 198 AesGcmHkdfStreamingKey aesGcmHkdfStreamingKey = 199 AesGcmHkdfStreamingKey.create( 200 aesGcmHkdfStreamingParameters, 201 SecretBytes.copyFrom( 202 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"), 203 InsecureSecretKeyAccess.get())); 204 AesCtrHmacStreamingParameters aesCtrHmacStreamingParameters = 205 AesCtrHmacStreamingParameters.builder() 206 .setKeySizeBytes(32) 207 .setDerivedKeySizeBytes(32) 208 .setHkdfHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 209 .setHmacHashType(AesCtrHmacStreamingParameters.HashType.SHA256) 210 .setHmacTagSizeBytes(16) 211 .setCiphertextSegmentSizeBytes(64) 212 .build(); 213 AesCtrHmacStreamingKey aesCtrHmacStreamingKey = 214 AesCtrHmacStreamingKey.create( 215 aesCtrHmacStreamingParameters, 216 SecretBytes.copyFrom( 217 Hex.decode("abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"), 218 InsecureSecretKeyAccess.get())); 219 KeysetHandle aesCtrHmacKeysetHandle = 220 KeysetHandle.newBuilder() 221 .addEntry(KeysetHandle.importKey(aesCtrHmacStreamingKey).withFixedId(43).makePrimary()) 222 .build(); 223 KeysetHandle aesGcmHkdfKeysetHandle = 224 KeysetHandle.newBuilder() 225 .addEntry(KeysetHandle.importKey(aesGcmHkdfStreamingKey).withFixedId(42).makePrimary()) 226 .build(); 227 228 StreamingAead aesCtrHmac = 229 aesCtrHmacKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 230 StreamingAead aesGcmHkdf = 231 aesGcmHkdfKeysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 232 233 assertThrows( 234 IOException.class, 235 () -> 236 StreamingTestUtil.testEncryptDecryptDifferentInstances( 237 aesCtrHmac, aesGcmHkdf, 0, 20, 5)); 238 assertThrows( 239 IOException.class, 240 () -> 241 StreamingTestUtil.testEncryptDecryptDifferentInstances( 242 aesGcmHkdf, aesCtrHmac, 0, 20, 5)); 243 } 244 245 @Test testEncryptDecryptWithTinkKey()246 public void testEncryptDecryptWithTinkKey() throws Exception { 247 com.google.crypto.tink.proto.AesGcmHkdfStreamingKey protoKey1 = 248 com.google.crypto.tink.proto.AesGcmHkdfStreamingKey.newBuilder() 249 .setVersion(0) 250 .setKeyValue(ByteString.copyFromUtf8("0123456789012345")) 251 .setParams( 252 com.google.crypto.tink.proto.AesGcmHkdfStreamingParams.newBuilder() 253 .setHkdfHashType(HashType.SHA1) 254 .setDerivedKeySize(16) 255 .setCiphertextSegmentSize(512 * 1024)) 256 .build(); 257 Keyset.Key keysetKey1 = 258 Keyset.Key.newBuilder() 259 .setKeyData( 260 KeyData.newBuilder() 261 .setTypeUrl(AES_GCM_HKDF_TYPE_URL) 262 .setValue(protoKey1.toByteString()) 263 .setKeyMaterialType(KeyMaterialType.SYMMETRIC)) 264 .setKeyId(1) 265 .setOutputPrefixType(OutputPrefixType.TINK) 266 .setStatus(KeyStatusType.ENABLED) 267 .build(); 268 com.google.crypto.tink.proto.AesGcmHkdfStreamingKey protoKey2 = 269 com.google.crypto.tink.proto.AesGcmHkdfStreamingKey.newBuilder() 270 .setVersion(0) 271 .setKeyValue(ByteString.copyFromUtf8("0123456789abcdef")) 272 .setParams( 273 com.google.crypto.tink.proto.AesGcmHkdfStreamingParams.newBuilder() 274 .setHkdfHashType(HashType.SHA1) 275 .setDerivedKeySize(16) 276 .setCiphertextSegmentSize(512 * 1024)) 277 .build(); 278 Keyset.Key keysetKey2 = 279 Keyset.Key.newBuilder() 280 .setKeyData( 281 KeyData.newBuilder() 282 .setTypeUrl(AES_GCM_HKDF_TYPE_URL) 283 .setValue(protoKey2.toByteString()) 284 .setKeyMaterialType(KeyMaterialType.SYMMETRIC)) 285 .setKeyId(2) 286 .setOutputPrefixType(OutputPrefixType.RAW) 287 .setStatus(KeyStatusType.ENABLED) 288 .build(); 289 290 Keyset keyset = 291 Keyset.newBuilder().addKey(keysetKey1).addKey(keysetKey2).setPrimaryKeyId(1).build(); 292 KeysetHandle keysetHandle = 293 TinkProtoKeysetFormat.parseKeyset(keyset.toByteArray(), InsecureSecretKeyAccess.get()); 294 StreamingAead streamingAead = 295 keysetHandle.getPrimitive(RegistryConfiguration.get(), StreamingAead.class); 296 297 StreamingTestUtil.testEncryptionAndDecryption(streamingAead, streamingAead); 298 } 299 300 @Test registerToInternalPrimitiveRegistry_works()301 public void registerToInternalPrimitiveRegistry_works() throws Exception { 302 PrimitiveRegistry.Builder initialBuilder = PrimitiveRegistry.builder(); 303 PrimitiveRegistry initialRegistry = initialBuilder.build(); 304 PrimitiveRegistry.Builder processedBuilder = PrimitiveRegistry.builder(initialRegistry); 305 306 StreamingAeadWrapper.registerToInternalPrimitiveRegistry(processedBuilder); 307 PrimitiveRegistry processedRegistry = processedBuilder.build(); 308 309 assertThrows( 310 GeneralSecurityException.class, 311 () -> initialRegistry.getInputPrimitiveClass(StreamingAead.class)); 312 assertThat(processedRegistry.getInputPrimitiveClass(StreamingAead.class)) 313 .isEqualTo(StreamingAead.class); 314 } 315 } 316