From 691f8b162dde84440dafd7dd1c27eb397099c308 Mon Sep 17 00:00:00 2001 From: Mohammad Derakhshani Date: Fri, 17 Jul 2020 13:47:17 -0700 Subject: [PATCH 1/3] minor cleanup --- .../AeadAes256CbcHmac256Algorithm.java | 2 +- .../CosmosDataEncryptionKeyProvider.java | 31 ++++++++++--- .../DataEncryptionKeyContainerCore.java | 2 +- .../EncryptionExceptionFactory.java | 12 +++-- .../encryption/EncryptionKeyWrapMetadata.java | 2 - .../encryption/SymmetricKey.java | 2 +- .../com/azure/cosmos/EncryptionTest2.java | 5 +-- .../DecryptDataEncryptedByDotNetTest.java | 6 +-- .../encryption/EncryptionProcessorTest.java | 4 +- .../encryption/EncryptionTests.java | 4 +- .../implementation/encryption/TestUtils.java | 2 +- .../cosmos/implementation/Constants.java | 5 --- .../encryption/EncryptionProcessor.java | 2 +- .../encryption/EncryptionProperties.java | 44 +++++++++---------- .../encryption/api/Constants.java | 12 +++++ .../api/CosmosEncryptionAlgorithm.java | 4 +- .../encryption/api/DataEncryptionKey.java | 5 +-- 17 files changed, 86 insertions(+), 58 deletions(-) create mode 100644 sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/AeadAes256CbcHmac256Algorithm.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/AeadAes256CbcHmac256Algorithm.java index 1d5a4317eb7f..7f99fa5ce5be 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/AeadAes256CbcHmac256Algorithm.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/AeadAes256CbcHmac256Algorithm.java @@ -91,7 +91,7 @@ public byte[] getRawKey() { @Override public String getEncryptionAlgorithm() { - return CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized; + return CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED; } /** diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java index 8fa62015fd2c..38d37710c88d 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java @@ -16,6 +16,10 @@ import java.time.Duration; import java.util.List; +/** + * Default implementation for a provider to get a data encryption key - wrapped keys are stored in a Cosmos DB container. + * See https://aka.ms/CosmosClientEncryption for more information on client-side encryption support in Azure Cosmos DB. + */ public class CosmosDataEncryptionKeyProvider implements DataEncryptionKeyProvider { // TODO: proper sample and documentation on container private static final String ContainerPartitionKeyPath = "/id"; @@ -23,14 +27,19 @@ public class CosmosDataEncryptionKeyProvider implements DataEncryptionKeyProvide // Is it a requirement on container definition? //Then the code-docs and samples needs to explicit cover it. private final DataEncryptionKeyContainerCore dataEncryptionKeyContainerCore; + private CosmosAsyncContainer container; private final DekCache DekCache; private final EncryptionKeyWrapProvider EncryptionKeyWrapProvider; - private CosmosAsyncContainer container; public CosmosDataEncryptionKeyProvider(EncryptionKeyWrapProvider encryptionKeyWrapProvider) { this(encryptionKeyWrapProvider, null); } + /** + * Initializes a new instance of the {@link CosmosDataEncryptionKeyProvider} + * @param encryptionKeyWrapProvider A provider that will be used to wrap (encrypt) and unwrap (decrypt) data encryption keys for envelope based encryption + * @param dekPropertiesTimeToLive Time to live for DEK properties before having to refresh. + */ public CosmosDataEncryptionKeyProvider(EncryptionKeyWrapProvider encryptionKeyWrapProvider, Duration dekPropertiesTimeToLive) { this.EncryptionKeyWrapProvider = encryptionKeyWrapProvider; @@ -46,10 +55,18 @@ CosmosAsyncContainer getContainer() { throw new IllegalStateException("The CosmosDataEncryptionKeyProvider was not initialized."); } + /** + * Gets a provider that will be used to wrap (encrypt) and unwrap (decrypt) data encryption keys for envelope based encryption. + * @return EncryptionKeyWrapProvider + */ EncryptionKeyWrapProvider getEncryptionKeyWrapProvider() { return EncryptionKeyWrapProvider; } + /** + * Gets Container for data encryption keys. + * @return DataEncryptionKeyContainer + */ DataEncryptionKeyContainer getDataEncryptionKeyContainer() { return dataEncryptionKeyContainerCore; } @@ -59,14 +76,18 @@ DekCache getDekCache() { } // TODO: @moderakh look into if this method needs to be async. + /** + * Initialize Cosmos DB container for CosmosDataEncryptionKeyProvider to store wrapped DEKs + * @param database Database + * @param containerId ontainer id + */ void initialize(CosmosAsyncDatabase database, - String containerId) { + String containerId) { Preconditions.checkNotNull(database, "database"); Preconditions.checkNotNull(containerId, "containerId"); - if (this.container != null) { - throw new IllegalStateException("CosmosDataEncryptionKeyProvider has already been initialized."); - } + Preconditions.checkState(this.container != null, "CosmosDataEncryptionKeyProvider has already been initialized."); + Preconditions.checkNotNull(database, "database is null"); CosmosContainerResponse containerResponse = database.createContainerIfNotExists(containerId, CosmosDataEncryptionKeyProvider.ContainerPartitionKeyPath).block(); List partitionKeyPath = containerResponse.getProperties().getPartitionKeyDefinition().getPaths(); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/DataEncryptionKeyContainerCore.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/DataEncryptionKeyContainerCore.java index 6013b7b24bbc..a1a4fe80ed84 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/DataEncryptionKeyContainerCore.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/DataEncryptionKeyContainerCore.java @@ -30,7 +30,7 @@ public Mono> createDataEncryptio Preconditions.checkArgument(StringUtils.isNotEmpty(id), "id is missing"); Preconditions.checkArgument(StringUtils.equals(encryptionAlgorithm, - CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized), "Unsupported Encryption Algorithm " + encryptionAlgorithm); + CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED), "Unsupported Encryption Algorithm " + encryptionAlgorithm); Preconditions.checkNotNull(encryptionKeyWrapMetadata, "encryptionKeyWrapMetadata is missing"); byte[] rawDek = DataEncryptionKey.generate(encryptionAlgorithm); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionExceptionFactory.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionExceptionFactory.java index 75d6f5d95a07..7f85e4f5e193 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionExceptionFactory.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionExceptionFactory.java @@ -13,19 +13,19 @@ public InvalidArgumentException(String msg, String argName) { } } - static RuntimeException invalidKeySize(String algorithmName, int actualKeylength, int expectedLength) { + static IllegalArgumentException invalidKeySize(String algorithmName, int actualKeylength, int expectedLength) { return new InvalidArgumentException( Strings.lenientFormat("Invalid key size for %s; actual: %s, expected: %s", algorithmName, actualKeylength, expectedLength), "dataEncryptionKey"); } - static RuntimeException invalidCipherTextSize(int actualSize, int minimumSize) { + static IllegalArgumentException invalidCipherTextSize(int actualSize, int minimumSize) { return new InvalidArgumentException( Strings.lenientFormat("Invalid cipher text size; actual: %s, minimum expected: %s.", actualSize, minimumSize), "cipherText"); } - static RuntimeException invalidAlgorithmVersion(byte actual, byte expected) { + static IllegalArgumentException invalidAlgorithmVersion(byte actual, byte expected) { return new InvalidArgumentException( Strings.lenientFormat("Invalid encryption algorithm version; actual: %s, expected: %s.", Bytes.toHex(actual), Bytes.toHex(expected)), "cipherText"); @@ -36,4 +36,10 @@ static RuntimeException invalidAuthenticationTag() { "Invalid authentication tag in cipher text.", "cipherText"); } + + static Exception exceptionKeyNotFoundException( + String message, + Exception innerException) { + return new IllegalArgumentException(message, innerException); + } } diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionKeyWrapMetadata.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionKeyWrapMetadata.java index 1bee51f35369..c22f0fb79691 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionKeyWrapMetadata.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionKeyWrapMetadata.java @@ -3,8 +3,6 @@ package com.azure.cosmos.implementation.encryption; -import com.azure.cosmos.implementation.Utils; -import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; import com.azure.cosmos.implementation.guava25.base.Preconditions; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/SymmetricKey.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/SymmetricKey.java index 0c25bac14d36..583b1463d5de 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/SymmetricKey.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/SymmetricKey.java @@ -29,7 +29,7 @@ class SymmetricKey { } /** - * Returns a copy of the plain text key + * Gets a copy of the plain text key * This is needed for actual encryption/decryption. * * @return root key byte array diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/EncryptionTest2.java b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/EncryptionTest2.java index b7a117f724cb..a6787a240507 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/EncryptionTest2.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/EncryptionTest2.java @@ -12,7 +12,6 @@ import com.azure.cosmos.models.CosmosItemRequestOptions; import com.azure.cosmos.models.CosmosItemResponse; import com.azure.cosmos.models.CosmosQueryRequestOptions; -import com.azure.cosmos.models.CosmosQueryRequestOptions; import com.azure.cosmos.models.FeedResponse; import com.azure.cosmos.models.ModelBridgeInternal; import com.azure.cosmos.models.PartitionKey; @@ -74,7 +73,7 @@ public void createItemEncrypt_readItemDecrypt() throws Exception { simpleInMemoryProvider.addKey(keyId, dataEncryptionKey); encryptionOptions.setDataEncryptionKeyId(keyId); - encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); ModelBridgeInternal.setEncryptionOptions(requestOptions, encryptionOptions); Pojo properties = getItem(UUID.randomUUID().toString()); @@ -100,7 +99,7 @@ public void upsertItem_readItem() throws Exception { encryptionOptions.setDataEncryptionKeyId(keyId); ModelBridgeInternal.setEncryptionOptions(requestOptions, encryptionOptions); - encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); Pojo properties = getItem(UUID.randomUUID().toString()); CosmosItemResponse itemResponse = container.upsertItem(properties, requestOptions); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/DecryptDataEncryptedByDotNetTest.java b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/DecryptDataEncryptedByDotNetTest.java index 372120586028..310dfccf18af 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/DecryptDataEncryptedByDotNetTest.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/DecryptDataEncryptedByDotNetTest.java @@ -94,10 +94,10 @@ public void canReadKeyEncryptionKeyGeneratedByDotNet() throws Exception { ObjectNode dataEncryptionKeyProperties = TestUtils.loadPojo("./encryption/dotnet/DataEncryptionKeyProperties.json", ObjectNode.class); keyContainer.createItem(dataEncryptionKeyProperties).block(); - DataEncryptionKey loadedKey = dekProvider.getDataEncryptionKey(dataEncryptionKeyProperties.get("id").asText(), CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + DataEncryptionKey loadedKey = dekProvider.getDataEncryptionKey(dataEncryptionKeyProperties.get("id").asText(), CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); - assertThat(loadedKey.getEncryptionAlgorithm()).isEqualTo(CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); - assertThat(loadedKey.getEncryptionAlgorithm()).isEqualTo(CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + assertThat(loadedKey.getEncryptionAlgorithm()).isEqualTo(CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); + assertThat(loadedKey.getEncryptionAlgorithm()).isEqualTo(CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); EncryptionKeyWrapMetadata keyWrapMetadata = Utils.getSimpleObjectMapper().convertValue(dataEncryptionKeyProperties.get("keyWrapMetadata"), EncryptionKeyWrapMetadata.class); byte[] expectedWrappedKey = dataEncryptionKeyProperties.get("wrappedDataEncryptionKey").binaryValue(); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionProcessorTest.java b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionProcessorTest.java index 18bdf0d6e3b5..05c478bb159c 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionProcessorTest.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionProcessorTest.java @@ -68,7 +68,7 @@ public byte[] getRawKey() { @Override public String getEncryptionAlgorithm() { - return CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized; + return CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED; } @Override @@ -89,7 +89,7 @@ public byte[] decryptData(byte[] cipherText) { com.azure.cosmos.implementation.encryption.api.EncryptionOptions encryptionOptions = new EncryptionOptions(); encryptionOptions.setPathsToEncrypt(ImmutableList.of("/sensitive")); encryptionOptions.setDataEncryptionKeyId(keyId); - encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); TestPojo testDate = getTestDate(); byte[] inputAsByteArray = toByteArray(testDate); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionTests.java b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionTests.java index 7eb5ab7c239f..bd653798c106 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionTests.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/EncryptionTests.java @@ -174,7 +174,7 @@ public void createItemEncrypt_readItemDecrypt() throws Exception { encryptionOptions.setPathsToEncrypt(ImmutableList.of("/Sensitive")); encryptionOptions.setDataEncryptionKeyId(dekId); - encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + encryptionOptions.setEncryptionAlgorithm(CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); ModelBridgeInternal.setEncryptionOptions(requestOptions, encryptionOptions); TestDoc properties = getItem(UUID.randomUUID().toString()); @@ -224,7 +224,7 @@ private TestDoc getItem(String documentId) { private static DataEncryptionKeyProperties createDek(CosmosDataEncryptionKeyProvider dekProvider, String dekId) { CosmosItemResponse dekResponse = dekProvider.getDataEncryptionKeyContainer().createDataEncryptionKeyAsync( dekId, - CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized, + CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED, EncryptionTests.metadata1, null).block(); assertThat(dekResponse.getRequestCharge()).isGreaterThan(0); diff --git a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/TestUtils.java b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/TestUtils.java index ef1a1bc10c5f..7543e12e265f 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/TestUtils.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/test/java/com/azure/cosmos/implementation/encryption/TestUtils.java @@ -88,7 +88,7 @@ public byte[] getRawKey() { @Override public String getEncryptionAlgorithm() { - return CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized; + return CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED; } @Override diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java index 7d67d54f3213..e741416872a8 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java @@ -199,11 +199,6 @@ public static final class Properties { public static final String KeyWrapMetadataType = "type"; public static final String KeyWrapMetadataValue = "value"; public static final String EncryptedInfo = "_ei"; -// public static final String DataEncryptionKeyRid = "_ek"; - public static final String EncryptionFormatVersion = "_ef"; - public static final String EncryptedData = "_ed"; - public static final String EncryptionAlgorithm = "_ea"; - public static final String DataEncryptionKeyId = "_en"; } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProcessor.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProcessor.java index e264f2486213..a9b0dc663d9c 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProcessor.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProcessor.java @@ -111,7 +111,7 @@ public ObjectNode decryptAsync( } // get key - DataEncryptionKey inMemoryRawDek = keyProvider.getDataEncryptionKey(encryptionProperties.getDataEncryptionKeyId(), CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + DataEncryptionKey inMemoryRawDek = keyProvider.getDataEncryptionKey(encryptionProperties.getDataEncryptionKeyId(), CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED); byte[] plainText = inMemoryRawDek.decryptData(encryptionProperties.getEncryptedData()); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java index d151e21a720a..67040068cbfa 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java @@ -3,10 +3,9 @@ package com.azure.cosmos.implementation.encryption; -import com.azure.cosmos.implementation.Constants; import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; +import com.azure.cosmos.implementation.encryption.api.Constants; import com.azure.cosmos.implementation.guava25.base.Preconditions; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; @@ -44,10 +43,10 @@ public static ObjectWriter getObjectWriter() { public ObjectNode toObjectNode() { ObjectNode objectNode = OBJECT_MAPPER.createObjectNode(); - objectNode.put(Constants.Properties.EncryptionFormatVersion, this.encryptionFormatVersion); - objectNode.put(Constants.Properties.EncryptionAlgorithm, this.encryptionAlgorithm); - objectNode.put(Constants.Properties.DataEncryptionKeyId, this.dataEncryptionKeyId); - objectNode.put(Constants.Properties.EncryptedData, this.encryptedData); + objectNode.put(Constants.EncryptionFormatVersion, this.encryptionFormatVersion); + objectNode.put(Constants.EncryptionAlgorithm, this.encryptionAlgorithm); + objectNode.put(Constants.DataEncryptionKeyId, this.dataEncryptionKeyId); + objectNode.put(Constants.EncryptedData, this.encryptedData); return objectNode; } @@ -74,7 +73,6 @@ public byte[] getEncryptedData() { return encryptedData; } - private String encryptionAlgorithm; private int encryptionFormatVersion; @@ -111,10 +109,10 @@ static final class JsonSerializer extends StdSerializer { @Override public void serialize(final EncryptionProperties value, final JsonGenerator generator, final SerializerProvider provider) throws IOException { generator.writeStartObject(); - generator.writeNumberField(Constants.Properties.EncryptionFormatVersion, value.encryptionFormatVersion); - generator.writeStringField(Constants.Properties.EncryptionAlgorithm, value.encryptionAlgorithm); - generator.writeStringField(Constants.Properties.DataEncryptionKeyId, value.dataEncryptionKeyId); - generator.writeBinaryField(Constants.Properties.EncryptedData, value.encryptedData); + generator.writeNumberField(Constants.EncryptionFormatVersion, value.encryptionFormatVersion); + generator.writeStringField(Constants.EncryptionAlgorithm, value.encryptionAlgorithm); + generator.writeStringField(Constants.DataEncryptionKeyId, value.dataEncryptionKeyId); + generator.writeBinaryField(Constants.EncryptedData, value.encryptedData); generator.writeEndObject(); } } @@ -141,24 +139,24 @@ public EncryptionProperties deserialize(JsonParser jsonParser, DeserializationCo EncryptionProperties encryptionProperties = new EncryptionProperties(); - JsonNode node = root.get(Constants.Properties.EncryptionFormatVersion); - Preconditions.checkNotNull(node, Constants.Properties.EncryptionFormatVersion + "can't deserialize"); - validateOrThrow(jsonParser, node.isInt(), Constants.Properties.EncryptionFormatVersion, "can't deserialize"); + JsonNode node = root.get(Constants.EncryptionFormatVersion); + Preconditions.checkNotNull(node, Constants.EncryptionFormatVersion + "can't deserialize"); + validateOrThrow(jsonParser, node.isInt(), Constants.EncryptionFormatVersion, "can't deserialize"); encryptionProperties.encryptionFormatVersion = node.asInt(); - node = root.get(Constants.Properties.EncryptionAlgorithm); - Preconditions.checkNotNull(node, Constants.Properties.EncryptionAlgorithm + "can't deserialize"); - validateOrThrow(jsonParser, node.isTextual(), Constants.Properties.EncryptionAlgorithm, "can't deserialize"); + node = root.get(Constants.EncryptionAlgorithm); + Preconditions.checkNotNull(node, Constants.EncryptionAlgorithm + "can't deserialize"); + validateOrThrow(jsonParser, node.isTextual(), Constants.EncryptionAlgorithm, "can't deserialize"); encryptionProperties.encryptionAlgorithm = node.asText(); - node = root.get(Constants.Properties.DataEncryptionKeyId); - Preconditions.checkNotNull(node, Constants.Properties.DataEncryptionKeyId + "can't deserialize"); - validateOrThrow(jsonParser, node.isTextual(), Constants.Properties.DataEncryptionKeyId, "can't deserialize"); + node = root.get(Constants.DataEncryptionKeyId); + Preconditions.checkNotNull(node, Constants.DataEncryptionKeyId + "can't deserialize"); + validateOrThrow(jsonParser, node.isTextual(), Constants.DataEncryptionKeyId, "can't deserialize"); encryptionProperties.dataEncryptionKeyId = node.asText(); - node = root.get(Constants.Properties.EncryptedData); - Preconditions.checkNotNull(node, Constants.Properties.EncryptedData + "can't deserialize"); - validateOrThrow(jsonParser, node.isBinary() || node.isTextual(), Constants.Properties.EncryptedData, "can't deserialize"); + node = root.get(Constants.EncryptedData); + Preconditions.checkNotNull(node, Constants.EncryptedData + "can't deserialize"); + validateOrThrow(jsonParser, node.isBinary() || node.isTextual(), Constants.EncryptedData, "can't deserialize"); encryptionProperties.encryptedData = node.binaryValue(); return encryptionProperties; diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java new file mode 100644 index 000000000000..2f4675805c05 --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.cosmos.implementation.encryption.api; + +public class Constants { + public static final String DocumentResourcePropertyName = "Documents"; + public static final String EncryptionFormatVersion = "_ef"; + public static final String EncryptionAlgorithm = "_ea"; + public static final String DataEncryptionKeyId = "_en"; + public static final String EncryptedData = "_ed"; +} diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/CosmosEncryptionAlgorithm.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/CosmosEncryptionAlgorithm.java index ebec258d5edb..4944ea40709f 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/CosmosEncryptionAlgorithm.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/CosmosEncryptionAlgorithm.java @@ -3,7 +3,7 @@ package com.azure.cosmos.implementation.encryption.api; -// TODO: enum string type? +// TODO: moderakh enum string type? /** * Algorithms for use with client-side encryption support in Azure Cosmos DB. @@ -13,6 +13,6 @@ public class CosmosEncryptionAlgorithm { /** * Authenticated Encryption algorithm based on https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05 */ - public static final String AEAes256CbcHmacSha256Randomized = "AEAes256CbcHmacSha256Randomized"; + public static final String AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED = "AEAes256CbcHmacSha256Randomized"; } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/DataEncryptionKey.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/DataEncryptionKey.java index 63e5957924d9..e844c4a1c350 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/DataEncryptionKey.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/DataEncryptionKey.java @@ -19,7 +19,6 @@ public interface DataEncryptionKey { */ byte[] getRawKey(); - /** * Gets Encryption algorithm to be used with this data encryption key. * @return encryption algorithm. @@ -46,7 +45,7 @@ public interface DataEncryptionKey { * @return New instance of data encryption key. */ static byte[] generate(String encryptionAlgorithm) { - if (!StringUtils.equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized)) { + if (!StringUtils.equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED)) { throw new IllegalArgumentException(String.format("Encryption algorithm not supported: {%s}", encryptionAlgorithm)); } @@ -79,7 +78,7 @@ static DataEncryptionKey create( throw new NullPointerException("rawKey"); } - if (!StringUtils.equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized)) { + if (!StringUtils.equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAES_256_CBC_HMAC_SHA_256_RANDOMIZED)) { throw new IllegalArgumentException(String.format("Encryption algorithm not supported: {%s}", encryptionAlgorithm)); } From 8eda32c50f77257ea46091b21a02819f253e9faf Mon Sep 17 00:00:00 2001 From: Mohammad Derakhshani Date: Fri, 17 Jul 2020 15:12:12 -0700 Subject: [PATCH 2/3] minor cleanup --- .../encryption/CosmosDataEncryptionKeyProvider.java | 2 +- .../encryption/api/EncryptionOptions.java | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java index 38d37710c88d..b3ba72ea6a34 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java @@ -27,9 +27,9 @@ public class CosmosDataEncryptionKeyProvider implements DataEncryptionKeyProvide // Is it a requirement on container definition? //Then the code-docs and samples needs to explicit cover it. private final DataEncryptionKeyContainerCore dataEncryptionKeyContainerCore; - private CosmosAsyncContainer container; private final DekCache DekCache; private final EncryptionKeyWrapProvider EncryptionKeyWrapProvider; + private CosmosAsyncContainer container; public CosmosDataEncryptionKeyProvider(EncryptionKeyWrapProvider encryptionKeyWrapProvider) { this(encryptionKeyWrapProvider, null); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/EncryptionOptions.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/EncryptionOptions.java index 8b0ef7e1292d..7f438ab16ffb 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/EncryptionOptions.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/EncryptionOptions.java @@ -5,9 +5,11 @@ import java.util.List; +/** + * Options for encryption of data. + */ public class EncryptionOptions { - /** * Gets Algorithm to be used for encrypting the data in the request payload. * @return @@ -16,18 +18,19 @@ public String getEncryptionAlgorithm() { return encryptionAlgorithm; } - /** * Sets Algorithm to be used for encrypting the data in the request payload. + * + * Authenticated Encryption algorithm based on https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05 + * is the only one supported and is represented by "AEAes256CbcHmacSha256Randomized" value. * @param encryptionAlgorithm - * @return + * @return the encryptionOptions */ public EncryptionOptions setEncryptionAlgorithm(String encryptionAlgorithm) { this.encryptionAlgorithm = encryptionAlgorithm; return this; } - /** * Gets Identifier of the data encryption key to be used for encrypting the data in the request payload. * The data encryption key must be suitable for use with the EncryptionAlgorithm provided. From 77cf2ec44b4f5aa2c9f572af53485db248b22b71 Mon Sep 17 00:00:00 2001 From: Mohammad Derakhshani Date: Fri, 17 Jul 2020 16:05:10 -0700 Subject: [PATCH 3/3] static field name correction, fixed pre-condition check --- .../CosmosDataEncryptionKeyProvider.java | 2 +- .../encryption/EncryptionProperties.java | 40 +++++++++---------- .../encryption/api/Constants.java | 10 ++--- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java index b3ba72ea6a34..848d048ebb27 100644 --- a/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java +++ b/sdk/cosmos/azure-cosmos-encryption/src/main/java/com/azure/cosmos/implementation/encryption/CosmosDataEncryptionKeyProvider.java @@ -86,7 +86,7 @@ void initialize(CosmosAsyncDatabase database, Preconditions.checkNotNull(database, "database"); Preconditions.checkNotNull(containerId, "containerId"); - Preconditions.checkState(this.container != null, "CosmosDataEncryptionKeyProvider has already been initialized."); + Preconditions.checkState(this.container == null, "CosmosDataEncryptionKeyProvider has already been initialized."); Preconditions.checkNotNull(database, "database is null"); CosmosContainerResponse containerResponse = database.createContainerIfNotExists(containerId, CosmosDataEncryptionKeyProvider.ContainerPartitionKeyPath).block(); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java index 67040068cbfa..c8948ce76075 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/EncryptionProperties.java @@ -43,10 +43,10 @@ public static ObjectWriter getObjectWriter() { public ObjectNode toObjectNode() { ObjectNode objectNode = OBJECT_MAPPER.createObjectNode(); - objectNode.put(Constants.EncryptionFormatVersion, this.encryptionFormatVersion); - objectNode.put(Constants.EncryptionAlgorithm, this.encryptionAlgorithm); - objectNode.put(Constants.DataEncryptionKeyId, this.dataEncryptionKeyId); - objectNode.put(Constants.EncryptedData, this.encryptedData); + objectNode.put(Constants.ENCRYPTION_FORMAT_VERSION, this.encryptionFormatVersion); + objectNode.put(Constants.ENCRYPTION_ALGORITHM, this.encryptionAlgorithm); + objectNode.put(Constants.DATA_ENCRYPTION_KEY_ID, this.dataEncryptionKeyId); + objectNode.put(Constants.ENCRYPTED_DATA, this.encryptedData); return objectNode; } @@ -109,10 +109,10 @@ static final class JsonSerializer extends StdSerializer { @Override public void serialize(final EncryptionProperties value, final JsonGenerator generator, final SerializerProvider provider) throws IOException { generator.writeStartObject(); - generator.writeNumberField(Constants.EncryptionFormatVersion, value.encryptionFormatVersion); - generator.writeStringField(Constants.EncryptionAlgorithm, value.encryptionAlgorithm); - generator.writeStringField(Constants.DataEncryptionKeyId, value.dataEncryptionKeyId); - generator.writeBinaryField(Constants.EncryptedData, value.encryptedData); + generator.writeNumberField(Constants.ENCRYPTION_FORMAT_VERSION, value.encryptionFormatVersion); + generator.writeStringField(Constants.ENCRYPTION_ALGORITHM, value.encryptionAlgorithm); + generator.writeStringField(Constants.DATA_ENCRYPTION_KEY_ID, value.dataEncryptionKeyId); + generator.writeBinaryField(Constants.ENCRYPTED_DATA, value.encryptedData); generator.writeEndObject(); } } @@ -139,24 +139,24 @@ public EncryptionProperties deserialize(JsonParser jsonParser, DeserializationCo EncryptionProperties encryptionProperties = new EncryptionProperties(); - JsonNode node = root.get(Constants.EncryptionFormatVersion); - Preconditions.checkNotNull(node, Constants.EncryptionFormatVersion + "can't deserialize"); - validateOrThrow(jsonParser, node.isInt(), Constants.EncryptionFormatVersion, "can't deserialize"); + JsonNode node = root.get(Constants.ENCRYPTION_FORMAT_VERSION); + Preconditions.checkNotNull(node, Constants.ENCRYPTION_FORMAT_VERSION + "can't deserialize"); + validateOrThrow(jsonParser, node.isInt(), Constants.ENCRYPTION_FORMAT_VERSION, "can't deserialize"); encryptionProperties.encryptionFormatVersion = node.asInt(); - node = root.get(Constants.EncryptionAlgorithm); - Preconditions.checkNotNull(node, Constants.EncryptionAlgorithm + "can't deserialize"); - validateOrThrow(jsonParser, node.isTextual(), Constants.EncryptionAlgorithm, "can't deserialize"); + node = root.get(Constants.ENCRYPTION_ALGORITHM); + Preconditions.checkNotNull(node, Constants.ENCRYPTION_ALGORITHM + "can't deserialize"); + validateOrThrow(jsonParser, node.isTextual(), Constants.ENCRYPTION_ALGORITHM, "can't deserialize"); encryptionProperties.encryptionAlgorithm = node.asText(); - node = root.get(Constants.DataEncryptionKeyId); - Preconditions.checkNotNull(node, Constants.DataEncryptionKeyId + "can't deserialize"); - validateOrThrow(jsonParser, node.isTextual(), Constants.DataEncryptionKeyId, "can't deserialize"); + node = root.get(Constants.DATA_ENCRYPTION_KEY_ID); + Preconditions.checkNotNull(node, Constants.DATA_ENCRYPTION_KEY_ID + "can't deserialize"); + validateOrThrow(jsonParser, node.isTextual(), Constants.DATA_ENCRYPTION_KEY_ID, "can't deserialize"); encryptionProperties.dataEncryptionKeyId = node.asText(); - node = root.get(Constants.EncryptedData); - Preconditions.checkNotNull(node, Constants.EncryptedData + "can't deserialize"); - validateOrThrow(jsonParser, node.isBinary() || node.isTextual(), Constants.EncryptedData, "can't deserialize"); + node = root.get(Constants.ENCRYPTED_DATA); + Preconditions.checkNotNull(node, Constants.ENCRYPTED_DATA + "can't deserialize"); + validateOrThrow(jsonParser, node.isBinary() || node.isTextual(), Constants.ENCRYPTED_DATA, "can't deserialize"); encryptionProperties.encryptedData = node.binaryValue(); return encryptionProperties; diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java index 2f4675805c05..c3e6e0130448 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/encryption/api/Constants.java @@ -4,9 +4,9 @@ package com.azure.cosmos.implementation.encryption.api; public class Constants { - public static final String DocumentResourcePropertyName = "Documents"; - public static final String EncryptionFormatVersion = "_ef"; - public static final String EncryptionAlgorithm = "_ea"; - public static final String DataEncryptionKeyId = "_en"; - public static final String EncryptedData = "_ed"; + public static final String DOCUMENT_RESOURCE_PROPERTY_NAME = "Documents"; + public static final String ENCRYPTION_FORMAT_VERSION = "_ef"; + public static final String ENCRYPTION_ALGORITHM = "_ea"; + public static final String DATA_ENCRYPTION_KEY_ID = "_en"; + public static final String ENCRYPTED_DATA = "_ed"; }