diff --git a/src/main/java/com/amazonaws/encryptionsdk/keyrings/DecryptionMaterials.java b/src/main/java/com/amazonaws/encryptionsdk/keyrings/DecryptionMaterials.java deleted file mode 100644 index 1cf84058e..000000000 --- a/src/main/java/com/amazonaws/encryptionsdk/keyrings/DecryptionMaterials.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except - * in compliance with the License. A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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.amazonaws.encryptionsdk.keyrings; - -import com.amazonaws.encryptionsdk.CryptoAlgorithm; - -import javax.crypto.SecretKey; -import java.security.PublicKey; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -import static java.util.Objects.requireNonNull; -import static org.apache.commons.lang3.Validate.isTrue; - -/** - * Contains the cryptographic materials needed for a decryption operation with Keyrings. - */ -public final class DecryptionMaterials { - private final CryptoAlgorithm algorithmSuite; - private SecretKey plaintextDataKey; - private final PublicKey verificationKey; - private final Map encryptionContext; - private final KeyringTrace keyringTrace; - - private DecryptionMaterials(Builder b) { - requireNonNull(b.algorithmSuite, "algorithmSuite is required"); - requireNonNull(b.keyringTrace, "keyringTrace is required"); - requireNonNull(b.encryptionContext, "encryptionContext is required"); - validatePlaintextDataKey(b.algorithmSuite, b.plaintextDataKey); - validateVerificationKey(b.algorithmSuite, b.verificationKey); - - algorithmSuite = b.algorithmSuite; - plaintextDataKey = b.plaintextDataKey; - verificationKey = b.verificationKey; - encryptionContext = b.encryptionContext; - keyringTrace = b.keyringTrace; - } - - /** - * The algorithm suite to use for this decryption operation. - */ - public CryptoAlgorithm getAlgorithmSuite() { - return algorithmSuite; - } - - /** - * Returns true if a plaintext data key has been populated. - * - * @return True if plaintext data key is populated, false otherwise. - */ - public boolean hasPlaintextDataKey() { - return this.plaintextDataKey != null; - } - - /** - * A data key to be used as input for encryption. - * - * @return The plaintext data key. - * @throws IllegalStateException if plaintext data key has not been populated. - */ - public SecretKey getPlaintextDataKey() throws IllegalStateException { - if (!hasPlaintextDataKey()) { - throw new IllegalStateException("plaintextDataKey has not been populated"); - } - return plaintextDataKey; - } - - /** - * Sets the plaintext data key. The plaintext data key must not already be populated. - * - * @param plaintextDataKey The plaintext data key. - * @param keyringTraceEntry The keyring trace entry recording this action. - */ - public void setPlaintextDataKey(SecretKey plaintextDataKey, KeyringTraceEntry keyringTraceEntry) { - if (hasPlaintextDataKey()) { - throw new IllegalStateException("plaintextDataKey was already populated"); - } - requireNonNull(plaintextDataKey, "plaintextDataKey is required"); - requireNonNull(keyringTraceEntry, "keyringTraceEntry is required"); - validatePlaintextDataKey(algorithmSuite, plaintextDataKey); - this.plaintextDataKey = plaintextDataKey; - keyringTrace.add(keyringTraceEntry); - } - - /** - * Returns true if verification key has been populated. - * - * @return True if verification key is populated, false otherwise. - */ - public boolean hasVerificationKey() { - return verificationKey != null; - } - - /** - * The verification key used for signature verification. - * - * @return The verification key. - * @throws IllegalStateException if a verification key has not been populated. - */ - public PublicKey getVerificationKey() throws IllegalStateException { - if (!hasVerificationKey()) { - throw new IllegalStateException(String.format( - "Signature verification is not supported by AlgorithmSuite %s", algorithmSuite.name())); - } - return verificationKey; - } - - public Map getEncryptionContext() { - return encryptionContext; - } - - public KeyringTrace getKeyringTrace() { - return keyringTrace; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DecryptionMaterials that = (DecryptionMaterials) o; - return algorithmSuite == that.algorithmSuite && - Objects.equals(plaintextDataKey, that.plaintextDataKey) && - Objects.equals(verificationKey, that.verificationKey) && - Objects.equals(encryptionContext, that.encryptionContext) && - Objects.equals(keyringTrace, that.keyringTrace); - } - - @Override - public int hashCode() { - return Objects.hash(algorithmSuite, plaintextDataKey, verificationKey, encryptionContext, keyringTrace); - } - - public static Builder newBuilder(CryptoAlgorithm algorithm) { - return new Builder(algorithm); - } - - public Builder toBuilder() { - return new Builder(this); - } - - private void validatePlaintextDataKey(CryptoAlgorithm algorithmSuite, SecretKey plaintextDataKey) throws IllegalArgumentException { - if (plaintextDataKey != null) { - isTrue(algorithmSuite.getDataKeyLength() == plaintextDataKey.getEncoded().length, - String.format("Incorrect key length. Expected %s but got %s", - algorithmSuite.getDataKeyLength(), plaintextDataKey.getEncoded().length)); - isTrue(algorithmSuite.getDataKeyAlgo().equalsIgnoreCase(plaintextDataKey.getAlgorithm()), - String.format("Incorrect key algorithm. Expected %s but got %s", - algorithmSuite.getDataKeyAlgo(), plaintextDataKey.getAlgorithm())); - } - } - - /** - * Validates that a verification key is specified if and only if - * the given algorithm suite supports signature verification. - */ - private void validateVerificationKey(CryptoAlgorithm algorithmSuite, PublicKey verificationKey) throws IllegalArgumentException { - if (algorithmSuite.getTrailingSignatureAlgo() == null && verificationKey != null) { - throw new IllegalArgumentException( - String.format("Algorithm Suite %s does not support signature verification", algorithmSuite.name())); - } else if (algorithmSuite.getTrailingSignatureAlgo() != null && verificationKey == null) { - throw new IllegalArgumentException( - String.format("Algorithm %s requires a verification key for signature verification", algorithmSuite.name())); - } - } - - public static final class Builder { - private CryptoAlgorithm algorithmSuite; - private SecretKey plaintextDataKey; - private PublicKey verificationKey; - private Map encryptionContext = Collections.emptyMap(); - private KeyringTrace keyringTrace = new KeyringTrace(); - - private Builder(CryptoAlgorithm algorithmSuite) { - this.algorithmSuite = algorithmSuite; - } - - private Builder(DecryptionMaterials result) { - this.algorithmSuite = result.algorithmSuite; - this.plaintextDataKey = result.plaintextDataKey; - this.verificationKey = result.verificationKey; - this.encryptionContext = result.encryptionContext; - this.keyringTrace = result.keyringTrace; - } - - public Builder algorithmSuite(CryptoAlgorithm algorithmSuite) { - this.algorithmSuite = algorithmSuite; - return this; - } - - public Builder plaintextDataKey(SecretKey plaintextDataKey) { - this.plaintextDataKey = plaintextDataKey; - return this; - } - - public Builder verificationKey(PublicKey verificationKey) { - this.verificationKey = verificationKey; - return this; - } - - public Builder encryptionContext(Map encryptionContext) { - this.encryptionContext = Collections.unmodifiableMap(new HashMap<>(encryptionContext)); - return this; - } - - public Builder keyringTrace(KeyringTrace keyringTrace) { - this.keyringTrace = keyringTrace; - return this; - } - - public DecryptionMaterials build() { - return new DecryptionMaterials(this); - } - } -} diff --git a/src/main/java/com/amazonaws/encryptionsdk/keyrings/EncryptionMaterials.java b/src/main/java/com/amazonaws/encryptionsdk/keyrings/EncryptionMaterials.java deleted file mode 100644 index d52f5d355..000000000 --- a/src/main/java/com/amazonaws/encryptionsdk/keyrings/EncryptionMaterials.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except - * in compliance with the License. A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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.amazonaws.encryptionsdk.keyrings; - -import com.amazonaws.encryptionsdk.CryptoAlgorithm; -import com.amazonaws.encryptionsdk.EncryptedDataKey; - -import javax.crypto.SecretKey; -import java.security.PrivateKey; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static java.util.Objects.requireNonNull; -import static org.apache.commons.lang3.Validate.isTrue; - -/** - * Contains the cryptographic materials needed for an encryption operation with Keyrings. - */ -public final class EncryptionMaterials { - private final CryptoAlgorithm algorithmSuite; - private final Map encryptionContext; - private final List encryptedDataKeys; - private SecretKey plaintextDataKey; - private final PrivateKey signingKey; - private final KeyringTrace keyringTrace; - - private EncryptionMaterials(Builder b) { - requireNonNull(b.algorithmSuite, "algorithmSuite is required"); - requireNonNull(b.keyringTrace, "keyringTrace is required"); - requireNonNull(b.encryptionContext, "encryptionContext is required"); - validatePlaintextDataKey(b.algorithmSuite, b.plaintextDataKey); - validateSigningKey(b.algorithmSuite, b.signingKey); - this.algorithmSuite = b.algorithmSuite; - this.encryptionContext = b.encryptionContext; - this.encryptedDataKeys = b.encryptedDataKeys; - this.plaintextDataKey = b.plaintextDataKey; - this.signingKey = b.signingKey; - this.keyringTrace = b.keyringTrace; - } - - public Builder toBuilder() { - return new Builder(this); - } - - public static Builder newBuilder(CryptoAlgorithm algorithmSuite) { - return new Builder(algorithmSuite); - } - - /** - * The algorithm suite to be used for encryption. - */ - public CryptoAlgorithm getAlgorithmSuite() { - return algorithmSuite; - } - - /** - * The encryption context associated with this encryption. - */ - public Map getEncryptionContext() { - return encryptionContext; - } - - /** - * An unmodifiable list of the encrypted data keys that correspond to the plaintext data key. - */ - public List getEncryptedDataKeys() { - return Collections.unmodifiableList(encryptedDataKeys); - } - - /** - * Add an encrypted data key to the list of encrypted data keys. - * - * @param encryptedDataKey The encrypted data key to add. - * @param keyringTraceEntry The keyring trace entry recording this action. - */ - public void addEncryptedDataKey(EncryptedDataKey encryptedDataKey, KeyringTraceEntry keyringTraceEntry) { - requireNonNull(encryptedDataKey, "encryptedDataKey is required"); - requireNonNull(keyringTraceEntry, "keyringTraceEntry is required"); - encryptedDataKeys.add(encryptedDataKey); - keyringTrace.add(keyringTraceEntry); - } - - /** - * Returns true if a plaintext data key has been populated. - * - * @return True if plaintext data key is populated, false otherwise. - */ - public boolean hasPlaintextDataKey() { - return this.plaintextDataKey != null; - } - - /** - * A data key to be used as input for encryption. - * - * @return The plaintext data key. - * @throws IllegalStateException if plain text data key has not been populated. - */ - public SecretKey getPlaintextDataKey() throws IllegalStateException { - if (!hasPlaintextDataKey()) { - throw new IllegalStateException("plaintextDataKey has not been populated"); - } - return plaintextDataKey; - } - - /** - * Sets the plaintext data key. The plaintext data key must not already be populated. - * - * @param plaintextDataKey The plaintext data key. - * @param keyringTraceEntry The keyring trace entry recording this action. - */ - public void setPlaintextDataKey(SecretKey plaintextDataKey, KeyringTraceEntry keyringTraceEntry) { - if (hasPlaintextDataKey()) { - throw new IllegalStateException("plaintextDataKey was already populated"); - } - requireNonNull(plaintextDataKey, "plaintextDataKey is required"); - requireNonNull(keyringTraceEntry, "keyringTraceEntry is required"); - validatePlaintextDataKey(algorithmSuite, plaintextDataKey); - this.plaintextDataKey = plaintextDataKey; - keyringTrace.add(keyringTraceEntry); - } - - /** - * Returns true if a signing key has been populated. - * - * @return True if signing key is populated, false otherwise. - */ - public boolean hasSigningKey() { - return this.signingKey != null; - } - - - /** - * The key to be used as the signing key for signature verification during encryption. - * - * @return The signing key. - * @throws IllegalStateException if signing key has not been populated. - */ - public PrivateKey getSigningKey() throws IllegalStateException { - if (!hasSigningKey()) { - throw new IllegalStateException(String.format( - "Signing is not supported by AlgorithmSuite %s", algorithmSuite.name())); - } - return signingKey; - } - - /** - * A keyring trace containing all of the actions that keyrings have taken on this set of encryption materials. - */ - public KeyringTrace getKeyringTrace() { - return keyringTrace; - } - - /** - * Validates that the given plaintext data key fits the specification - * for the data key algorithm specified in the given algorithm suite. - */ - private void validatePlaintextDataKey(CryptoAlgorithm algorithmSuite, SecretKey plaintextDataKey) throws IllegalArgumentException { - if (plaintextDataKey != null) { - isTrue(algorithmSuite.getDataKeyLength() == plaintextDataKey.getEncoded().length, - String.format("Incorrect data key length. Expected %s but got %s", - algorithmSuite.getDataKeyLength(), plaintextDataKey.getEncoded().length)); - isTrue(algorithmSuite.getDataKeyAlgo().equalsIgnoreCase(plaintextDataKey.getAlgorithm()), - String.format("Incorrect data key algorithm. Expected %s but got %s", - algorithmSuite.getDataKeyAlgo(), plaintextDataKey.getAlgorithm())); - } - } - - /** - * Validates that a signing key is specified only if and only if - * the given algorithm suite supports signature verification. - */ - private void validateSigningKey(CryptoAlgorithm algorithmSuite, PrivateKey signingKey) throws IllegalArgumentException { - if (algorithmSuite.getTrailingSignatureAlgo() == null && signingKey != null) { - throw new IllegalArgumentException( - String.format("Algorithm Suite %s does not support signing", algorithmSuite.name())); - } else if (algorithmSuite.getTrailingSignatureAlgo() != null && signingKey == null) { - throw new IllegalArgumentException( - String.format("Algorithm Suite %s requires a signing key for signing", algorithmSuite.name())); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - EncryptionMaterials that = (EncryptionMaterials) o; - return algorithmSuite == that.algorithmSuite && - Objects.equals(encryptionContext, that.encryptionContext) && - Objects.equals(encryptedDataKeys, that.encryptedDataKeys) && - Objects.equals(plaintextDataKey, that.plaintextDataKey) && - Objects.equals(signingKey, that.signingKey) && - Objects.equals(keyringTrace, that.keyringTrace); - } - - @Override - public int hashCode() { - return Objects.hash(algorithmSuite, encryptionContext, encryptedDataKeys, plaintextDataKey, signingKey, keyringTrace); - } - - public static class Builder { - private CryptoAlgorithm algorithmSuite; - private Map encryptionContext = Collections.emptyMap(); - private List encryptedDataKeys = new ArrayList<>(); - private SecretKey plaintextDataKey; - private PrivateKey signingKey; - private KeyringTrace keyringTrace = new KeyringTrace(); - - private Builder(CryptoAlgorithm algorithmSuite) { - this.algorithmSuite = algorithmSuite; - } - - private Builder(EncryptionMaterials r) { - algorithmSuite = r.algorithmSuite; - encryptionContext = r.encryptionContext; - encryptedDataKeys = r.encryptedDataKeys; - plaintextDataKey = r.plaintextDataKey; - signingKey = r.signingKey; - keyringTrace = r.keyringTrace; - } - - public EncryptionMaterials build() { - return new EncryptionMaterials(this); - } - - public Builder algorithmSuite(CryptoAlgorithm algorithmSuite) { - this.algorithmSuite = algorithmSuite; - return this; - } - - public Builder encryptionContext(Map encryptionContext) { - this.encryptionContext = Collections.unmodifiableMap(new HashMap<>(encryptionContext)); - return this; - } - - public Builder encryptedDataKeys(List encryptedDataKeys) { - this.encryptedDataKeys = new ArrayList<>(encryptedDataKeys); - return this; - } - - public Builder plaintextDataKey(SecretKey plaintextDataKey) { - this.plaintextDataKey = plaintextDataKey; - return this; - } - - public Builder signingKey(PrivateKey signingKey) { - this.signingKey = signingKey; - return this; - } - - public Builder keyringTrace(KeyringTrace keyringTrace) { - this.keyringTrace = keyringTrace; - return this; - } - } -} diff --git a/src/main/java/com/amazonaws/encryptionsdk/keyrings/Keyring.java b/src/main/java/com/amazonaws/encryptionsdk/keyrings/Keyring.java index 20f4c69f5..93002270d 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/keyrings/Keyring.java +++ b/src/main/java/com/amazonaws/encryptionsdk/keyrings/Keyring.java @@ -14,6 +14,8 @@ package com.amazonaws.encryptionsdk.keyrings; import com.amazonaws.encryptionsdk.EncryptedDataKey; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import java.util.List; diff --git a/src/main/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyring.java b/src/main/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyring.java index 4b3974501..528b4a1dc 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyring.java +++ b/src/main/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyring.java @@ -21,6 +21,9 @@ import com.amazonaws.encryptionsdk.kms.DataKeyEncryptionDao.DecryptDataKeyResult; import com.amazonaws.encryptionsdk.kms.DataKeyEncryptionDao.GenerateDataKeyResult; import com.amazonaws.encryptionsdk.kms.KmsUtils; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; +import com.amazonaws.encryptionsdk.model.KeyBlob; import java.util.ArrayList; import java.util.HashSet; @@ -77,7 +80,7 @@ public void onEncrypt(EncryptionMaterials encryptionMaterials) { // If the input encryption materials do not contain a plaintext data key and this keyring does not // have a generator defined, OnEncrypt MUST not modify the encryption materials and MUST fail. - if (!encryptionMaterials.hasPlaintextDataKey() && generatorKeyId == null) { + if (!encryptionMaterials.hasCleartextDataKey() && generatorKeyId == null) { throw new AwsCryptoException("Encryption materials must contain either a plaintext data key or a generator"); } @@ -85,7 +88,7 @@ public void onEncrypt(EncryptionMaterials encryptionMaterials) { // If the input encryption materials do not contain a plaintext data key and a generator is defined onEncrypt // MUST attempt to generate a new plaintext data key and encrypt that data key by calling KMS GenerateDataKey. - if (!encryptionMaterials.hasPlaintextDataKey()) { + if (!encryptionMaterials.hasCleartextDataKey()) { generateDataKey(encryptionMaterials); } else if (generatorKeyId != null) { // If this keyring's generator is defined and was not used to generate a data key, OnEncrypt @@ -102,19 +105,19 @@ public void onEncrypt(EncryptionMaterials encryptionMaterials) { private void generateDataKey(final EncryptionMaterials encryptionMaterials) { final GenerateDataKeyResult result = dataKeyEncryptionDao.generateDataKey(generatorKeyId, - encryptionMaterials.getAlgorithmSuite(), encryptionMaterials.getEncryptionContext()); + encryptionMaterials.getAlgorithm(), encryptionMaterials.getEncryptionContext()); - encryptionMaterials.setPlaintextDataKey(result.getPlaintextDataKey(), + encryptionMaterials.setCleartextDataKey(result.getPlaintextDataKey(), new KeyringTraceEntry(KMS_PROVIDER_ID, generatorKeyId, KeyringTraceFlag.GENERATED_DATA_KEY)); - encryptionMaterials.addEncryptedDataKey(result.getEncryptedDataKey(), + encryptionMaterials.addEncryptedDataKey(new KeyBlob(result.getEncryptedDataKey()), new KeyringTraceEntry(KMS_PROVIDER_ID, generatorKeyId, KeyringTraceFlag.ENCRYPTED_DATA_KEY, KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT)); } private void encryptDataKey(final String keyId, final EncryptionMaterials encryptionMaterials) { final EncryptedDataKey encryptedDataKey = dataKeyEncryptionDao.encryptDataKey(keyId, - encryptionMaterials.getPlaintextDataKey(), encryptionMaterials.getEncryptionContext()); + encryptionMaterials.getCleartextDataKey(), encryptionMaterials.getEncryptionContext()); - encryptionMaterials.addEncryptedDataKey(encryptedDataKey, + encryptionMaterials.addEncryptedDataKey(new KeyBlob(encryptedDataKey), new KeyringTraceEntry(KMS_PROVIDER_ID, keyId, KeyringTraceFlag.ENCRYPTED_DATA_KEY, KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT)); } @@ -123,7 +126,7 @@ public void onDecrypt(DecryptionMaterials decryptionMaterials, List> implements Keyring { - - private final MasterKeyProvider masterKeyProvider; - - MasterKeyProviderKeyring(MasterKeyProvider masterKeyProvider) { - requireNonNull(masterKeyProvider, "masterKeyProvider is required"); - - this.masterKeyProvider = masterKeyProvider; - } - - @Override - public void onEncrypt(EncryptionMaterials encryptionMaterials) { - requireNonNull(encryptionMaterials, "encryptionMaterials are required"); - - final List masterKeys = masterKeyProvider.getMasterKeysForEncryption(MasterKeyRequest.newBuilder() - .setEncryptionContext(encryptionMaterials.getEncryptionContext()).build()); - - if (masterKeys == null || masterKeys.isEmpty()) { - throw new AwsCryptoException("No master keys available from the master key provider."); - } - - final K primaryMasterKey = masterKeys.get(0); - final List masterKeysToEncryptWith = new ArrayList<>(masterKeys); - - if (!encryptionMaterials.hasPlaintextDataKey()) { - final DataKey dataKey = primaryMasterKey.generateDataKey( - encryptionMaterials.getAlgorithmSuite(), encryptionMaterials.getEncryptionContext()); - encryptionMaterials.setPlaintextDataKey(dataKey.getKey(), new KeyringTraceEntry( - primaryMasterKey.getProviderId(), primaryMasterKey.getKeyId(), KeyringTraceFlag.GENERATED_DATA_KEY)); - encryptionMaterials.addEncryptedDataKey(dataKey, encryptTraceEntry(primaryMasterKey)); - // The primary master key has already been used for encryption, so remove it from the list to encrypt with - masterKeysToEncryptWith.remove(primaryMasterKey); - } - - final DataKey dataKey = new DataKey<>(encryptionMaterials.getPlaintextDataKey(), EMPTY_BYTE_ARRAY, - EMPTY_BYTE_ARRAY, primaryMasterKey); - - for (K masterKey : masterKeysToEncryptWith) { - final EncryptedDataKey encryptedDataKey = masterKey.encryptDataKey(encryptionMaterials.getAlgorithmSuite(), - encryptionMaterials.getEncryptionContext(), dataKey); - encryptionMaterials.addEncryptedDataKey(encryptedDataKey, encryptTraceEntry(masterKey)); - } - } - - @Override - public void onDecrypt(DecryptionMaterials decryptionMaterials, List encryptedDataKeys) { - requireNonNull(decryptionMaterials, "decryptionMaterials are required"); - requireNonNull(encryptedDataKeys, "encryptedDataKeys are required"); - - if (decryptionMaterials.hasPlaintextDataKey()) { - return; - } - - final DataKey dataKey; - try { - dataKey = masterKeyProvider.decryptDataKey(decryptionMaterials.getAlgorithmSuite(), encryptedDataKeys, - decryptionMaterials.getEncryptionContext()); - } catch (CannotUnwrapDataKeyException e) { - return; - } - - decryptionMaterials.setPlaintextDataKey(dataKey.getKey(), decryptTraceEntry(dataKey.getMasterKey())); - } - - private boolean signedEncryptionContext(MasterKey masterKey) { - if (masterKey instanceof KmsMasterKey) { - return true; - } - - if (masterKey instanceof JceMasterKey) { - return ((JceMasterKey) masterKey).isEncryptionContextSigned(); - } - - return false; - } - - private KeyringTraceEntry encryptTraceEntry(MasterKey masterKey) { - final List flags = new ArrayList<>(); - flags.add(ENCRYPTED_DATA_KEY); - - if (signedEncryptionContext(masterKey)) { - flags.add(SIGNED_ENCRYPTION_CONTEXT); - } - - return new KeyringTraceEntry(masterKey.getProviderId(), masterKey.getKeyId(), flags.toArray(new KeyringTraceFlag[]{})); - } - - private KeyringTraceEntry decryptTraceEntry(MasterKey masterKey) { - final List flags = new ArrayList<>(); - flags.add(DECRYPTED_DATA_KEY); - - if (signedEncryptionContext(masterKey)) { - flags.add(VERIFIED_ENCRYPTION_CONTEXT); - } - - return new KeyringTraceEntry(masterKey.getProviderId(), masterKey.getKeyId(), flags.toArray(new KeyringTraceFlag[]{})); - } -} diff --git a/src/main/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyring.java b/src/main/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyring.java index 7d957b281..ce6d9600c 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyring.java +++ b/src/main/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyring.java @@ -16,6 +16,8 @@ import com.amazonaws.encryptionsdk.EncryptedDataKey; import com.amazonaws.encryptionsdk.exception.AwsCryptoException; import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import java.util.ArrayList; import java.util.List; @@ -50,9 +52,9 @@ public void onEncrypt(EncryptionMaterials encryptionMaterials) { generatorKeyring.onEncrypt(encryptionMaterials); } - if (!encryptionMaterials.hasPlaintextDataKey()) { - throw new AwsCryptoException("Either a generator keyring must be supplied that produces a plaintext " + - "data key or a plaintext data key must already be present in the encryption materials."); + if (!encryptionMaterials.hasCleartextDataKey()) { + throw new AwsCryptoException("Either a generator keyring must be supplied that produces a cleartext " + + "data key or a cleartext data key must already be present in the encryption materials."); } for (Keyring keyring : childrenKeyrings) { @@ -65,7 +67,7 @@ public void onDecrypt(DecryptionMaterials decryptionMaterials, List masterKeyProvider) { - return new MasterKeyProviderKeyring<>(masterKeyProvider); - } /** * Constructs a {@code Keyring} which interacts with AWS Key Management Service (KMS) to create, diff --git a/src/main/java/com/amazonaws/encryptionsdk/model/DecryptionMaterials.java b/src/main/java/com/amazonaws/encryptionsdk/model/DecryptionMaterials.java index 94423b884..722246237 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/model/DecryptionMaterials.java +++ b/src/main/java/com/amazonaws/encryptionsdk/model/DecryptionMaterials.java @@ -1,26 +1,96 @@ package com.amazonaws.encryptionsdk.model; +import com.amazonaws.encryptionsdk.CryptoAlgorithm; +import com.amazonaws.encryptionsdk.DataKey; +import com.amazonaws.encryptionsdk.keyrings.KeyringTrace; +import com.amazonaws.encryptionsdk.keyrings.KeyringTraceEntry; + +import javax.crypto.SecretKey; import java.security.PublicKey; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; -import com.amazonaws.encryptionsdk.DataKey; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY; +import static org.apache.commons.lang3.Validate.isTrue; public final class DecryptionMaterials { - private final DataKey dataKey; + private final CryptoAlgorithm algorithm; + private final Map encryptionContext; + private DataKey dataKey; private final PublicKey trailingSignatureKey; + private final KeyringTrace keyringTrace; private DecryptionMaterials(Builder b) { + algorithm = b.algorithm; + encryptionContext = b.encryptionContext; dataKey = b.getDataKey(); trailingSignatureKey = b.getTrailingSignatureKey(); + keyringTrace = b.keyringTrace; } + /** + * The algorithm suite to use for this decryption operation. + */ + public CryptoAlgorithm getAlgorithm() { + return algorithm; + } + + /** + * The encryption context + */ + public Map getEncryptionContext() { + return encryptionContext; + } + + /** + * @deprecated Replaced by {@link #getCleartextDataKey()} + */ + @Deprecated public DataKey getDataKey() { return dataKey; } + /** + * Sets the cleartext data key. The cleartext data key must not already be populated. + * + * @param cleartextDataKey The cleartext data key. + * @param keyringTraceEntry The keyring trace entry recording this action. + */ + public void setCleartextDataKey(SecretKey cleartextDataKey, KeyringTraceEntry keyringTraceEntry) { + if (hasCleartextDataKey()) { + throw new IllegalStateException("cleartextDataKey was already populated"); + } + requireNonNull(cleartextDataKey, "cleartextDataKey is required"); + requireNonNull(keyringTraceEntry, "keyringTraceEntry is required"); + validateCleartextDataKey(algorithm, cleartextDataKey); + this.dataKey = new DataKey<>(cleartextDataKey, EMPTY_BYTE_ARRAY, EMPTY_BYTE_ARRAY, null); + keyringTrace.add(keyringTraceEntry); + } + + public SecretKey getCleartextDataKey() { + return dataKey == null ? null : dataKey.getKey(); + } + + /** + * Returns true if a cleartext data key has been populated. + * + * @return True if cleartext data key is populated, false otherwise. + */ + public boolean hasCleartextDataKey() { + return this.dataKey != null; + } + public PublicKey getTrailingSignatureKey() { return trailingSignatureKey; } + public KeyringTrace getKeyringTrace() { + return keyringTrace; + } + public static Builder newBuilder() { return new Builder(); } @@ -29,26 +99,94 @@ public Builder toBuilder() { return new Builder(this); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DecryptionMaterials that = (DecryptionMaterials) o; + + return algorithm == that.algorithm && + Objects.equals(getCleartextDataKey(), that.getCleartextDataKey()) && + Objects.equals(trailingSignatureKey, that.trailingSignatureKey) && + Objects.equals(encryptionContext, that.encryptionContext) && + Objects.equals(keyringTrace, that.keyringTrace); + } + + @Override + public int hashCode() { + return Objects.hash(algorithm, getCleartextDataKey(), trailingSignatureKey, encryptionContext, keyringTrace); + } + + private void validateCleartextDataKey(CryptoAlgorithm algorithm, SecretKey cleartextDataKey) throws IllegalArgumentException { + if (algorithm != null && cleartextDataKey != null) { + isTrue(algorithm.getDataKeyLength() == cleartextDataKey.getEncoded().length, + String.format("Incorrect key length. Expected %s but got %s", + algorithm.getDataKeyLength(), cleartextDataKey.getEncoded().length)); + isTrue(algorithm.getDataKeyAlgo().equalsIgnoreCase(cleartextDataKey.getAlgorithm()), + String.format("Incorrect key algorithm. Expected %s but got %s", + algorithm.getDataKeyAlgo(), cleartextDataKey.getAlgorithm())); + } + } + public static final class Builder { + private CryptoAlgorithm algorithm; + private Map encryptionContext = Collections.emptyMap(); private DataKey dataKey; private PublicKey trailingSignatureKey; + private KeyringTrace keyringTrace = new KeyringTrace(); private Builder(DecryptionMaterials result) { + this.algorithm = result.getAlgorithm(); + this.encryptionContext = result.getEncryptionContext(); this.dataKey = result.getDataKey(); this.trailingSignatureKey = result.getTrailingSignatureKey(); + this.keyringTrace = result.keyringTrace; } private Builder() {} + public CryptoAlgorithm getAlgorithm() { + return algorithm; + } + + public Builder setAlgorithm(CryptoAlgorithm algorithm) { + requireNonNull(algorithm, "algorithm is required"); + this.algorithm = algorithm; + return this; + } + + public Map getEncryptionContext() { + return encryptionContext; + } + + public Builder setEncryptionContext(Map encryptionContext) { + requireNonNull(encryptionContext, "encryptionContext is required"); + this.encryptionContext = Collections.unmodifiableMap(new HashMap<>(encryptionContext)); + return this; + } + + @Deprecated public DataKey getDataKey() { return dataKey; } + @Deprecated public Builder setDataKey(DataKey dataKey) { this.dataKey = dataKey; return this; } + /** + * Sets the cleartext data key. + * + * @param cleartextDataKey The cleartext data key. + */ + public Builder setCleartextDataKey(SecretKey cleartextDataKey) { + requireNonNull(cleartextDataKey, "cleartextDataKey is required"); + this.dataKey = new DataKey<>(cleartextDataKey, EMPTY_BYTE_ARRAY, EMPTY_BYTE_ARRAY, null); + return this; + } + public PublicKey getTrailingSignatureKey() { return trailingSignatureKey; } @@ -58,6 +196,16 @@ public Builder setTrailingSignatureKey(PublicKey trailingSignatureKey) { return this; } + public KeyringTrace getKeyringTrace() { + return keyringTrace; + } + + public Builder setKeyringTrace(KeyringTrace keyringTrace) { + requireNonNull(keyringTrace, "keyringTrace is required"); + this.keyringTrace = keyringTrace; + return this; + } + public DecryptionMaterials build() { return new DecryptionMaterials(this); } diff --git a/src/main/java/com/amazonaws/encryptionsdk/model/EncryptionMaterials.java b/src/main/java/com/amazonaws/encryptionsdk/model/EncryptionMaterials.java index 1a40d7c36..ed46dabf8 100644 --- a/src/main/java/com/amazonaws/encryptionsdk/model/EncryptionMaterials.java +++ b/src/main/java/com/amazonaws/encryptionsdk/model/EncryptionMaterials.java @@ -1,5 +1,11 @@ package com.amazonaws.encryptionsdk.model; +import com.amazonaws.encryptionsdk.CryptoAlgorithm; +import com.amazonaws.encryptionsdk.MasterKey; +import com.amazonaws.encryptionsdk.keyrings.Keyring; +import com.amazonaws.encryptionsdk.keyrings.KeyringTrace; +import com.amazonaws.encryptionsdk.keyrings.KeyringTraceEntry; + import javax.crypto.SecretKey; import java.security.PrivateKey; import java.util.ArrayList; @@ -9,8 +15,9 @@ import java.util.Map; import java.util.Objects; -import com.amazonaws.encryptionsdk.CryptoAlgorithm; -import com.amazonaws.encryptionsdk.MasterKey; +import static java.util.Collections.unmodifiableList; +import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang3.Validate.isTrue; /** * Contains the cryptographic materials needed for an encryption operation. @@ -21,9 +28,10 @@ public final class EncryptionMaterials { private final CryptoAlgorithm algorithm; private final Map encryptionContext; private final List encryptedDataKeys; - private final SecretKey cleartextDataKey; + private SecretKey cleartextDataKey; private final PrivateKey trailingSignatureKey; private final List masterKeys; + private final KeyringTrace keyringTrace; private EncryptionMaterials(Builder b) { this.algorithm = b.algorithm; @@ -32,6 +40,7 @@ private EncryptionMaterials(Builder b) { this.cleartextDataKey = b.cleartextDataKey; this.trailingSignatureKey = b.trailingSignatureKey; this.masterKeys = b.getMasterKeys(); + this.keyringTrace = b.keyringTrace; } public Builder toBuilder() { @@ -61,7 +70,20 @@ public Map getEncryptionContext() { * The KeyBlobs to serialize (in cleartext) into the encrypted message. */ public List getEncryptedDataKeys() { - return encryptedDataKeys; + return unmodifiableList(encryptedDataKeys); + } + + /** + * Add an encrypted data key to the list of encrypted data keys. + * + * @param encryptedDataKey The encrypted data key to add. + * @param keyringTraceEntry The keyring trace entry recording this action. + */ + public void addEncryptedDataKey(KeyBlob encryptedDataKey, KeyringTraceEntry keyringTraceEntry) { + requireNonNull(encryptedDataKey, "encryptedDataKey is required"); + requireNonNull(keyringTraceEntry, "keyringTraceEntry is required"); + encryptedDataKeys.add(encryptedDataKey); + keyringTrace.add(keyringTraceEntry); } /** @@ -72,6 +94,32 @@ public SecretKey getCleartextDataKey() { return cleartextDataKey; } + /** + * Sets the cleartext data key. The cleartext data key must not already be populated. + * + * @param cleartextDataKey The cleartext data key. + * @param keyringTraceEntry The keyring trace entry recording this action. + */ + public void setCleartextDataKey(SecretKey cleartextDataKey, KeyringTraceEntry keyringTraceEntry) { + if (hasCleartextDataKey()) { + throw new IllegalStateException("cleartextDataKey was already populated"); + } + requireNonNull(cleartextDataKey, "cleartextDataKey is required"); + requireNonNull(keyringTraceEntry, "keyringTraceEntry is required"); + validateCleartextDataKey(algorithm, cleartextDataKey); + this.cleartextDataKey = cleartextDataKey; + keyringTrace.add(keyringTraceEntry); + } + + /** + * Returns true if a cleartext data key has been populated. + * + * @return True is a cleartext data key has been populated, false otherwise. + */ + public boolean hasCleartextDataKey() { + return this.cleartextDataKey != null; + } + /** * The private key to be used to sign the message trailer. Must be present if any only if required by the * crypto algorithm, and the key type must likewise match the algorithm in use. @@ -86,11 +134,36 @@ public PrivateKey getTrailingSignatureKey() { /** * Contains a list of all MasterKeys that could decrypt this message. + * + * @deprecated {@link MasterKey}s have been replaced by {@link Keyring}s */ + @Deprecated public List getMasterKeys() { return masterKeys; } + /** + * A keyring trace containing all of the actions that keyrings have taken on this set of encryption materials. + */ + public KeyringTrace getKeyringTrace() { + return keyringTrace; + } + + /** + * Validates that the given plaintext data key fits the specification + * for the data key algorithm specified in the given algorithm suite. + */ + private void validateCleartextDataKey(CryptoAlgorithm algorithmSuite, SecretKey cleartextDataKey) throws IllegalArgumentException { + if (algorithmSuite != null && cleartextDataKey != null) { + isTrue(algorithmSuite.getDataKeyLength() == cleartextDataKey.getEncoded().length, + String.format("Incorrect data key length. Expected %s but got %s", + algorithmSuite.getDataKeyLength(), cleartextDataKey.getEncoded().length)); + isTrue(algorithmSuite.getDataKeyAlgo().equalsIgnoreCase(cleartextDataKey.getAlgorithm()), + String.format("Incorrect data key algorithm. Expected %s but got %s", + algorithmSuite.getDataKeyAlgo(), cleartextDataKey.getAlgorithm())); + } + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -100,21 +173,23 @@ public List getMasterKeys() { Objects.equals(encryptedDataKeys, that.encryptedDataKeys) && Objects.equals(cleartextDataKey, that.cleartextDataKey) && Objects.equals(trailingSignatureKey, that.trailingSignatureKey) && - Objects.equals(masterKeys, that.masterKeys); + Objects.equals(masterKeys, that.masterKeys) && + Objects.equals(keyringTrace, that.keyringTrace); } @Override public int hashCode() { return Objects.hash(algorithm, encryptionContext, encryptedDataKeys, cleartextDataKey, trailingSignatureKey, - masterKeys); + masterKeys, keyringTrace); } public static class Builder { private CryptoAlgorithm algorithm; private Map encryptionContext = Collections.emptyMap(); - private List encryptedDataKeys = null; + private List encryptedDataKeys = new ArrayList<>(); private SecretKey cleartextDataKey; private PrivateKey trailingSignatureKey; private List masterKeys = Collections.emptyList(); + private KeyringTrace keyringTrace = new KeyringTrace(); private Builder() {} @@ -125,6 +200,7 @@ private Builder(EncryptionMaterials r) { cleartextDataKey = r.cleartextDataKey; trailingSignatureKey = r.trailingSignatureKey; setMasterKeys(r.masterKeys); + keyringTrace = r.keyringTrace; } public EncryptionMaterials build() { @@ -154,7 +230,7 @@ public List getEncryptedDataKeys() { } public Builder setEncryptedDataKeys(List encryptedDataKeys) { - this.encryptedDataKeys = Collections.unmodifiableList(new ArrayList<>(encryptedDataKeys)); + this.encryptedDataKeys = new ArrayList<>(encryptedDataKeys); return this; } @@ -176,12 +252,23 @@ public Builder setTrailingSignatureKey(PrivateKey trailingSignatureKey) { return this; } + @Deprecated public List getMasterKeys() { return masterKeys; } + @Deprecated public Builder setMasterKeys(List masterKeys) { - this.masterKeys = Collections.unmodifiableList(new ArrayList<>(masterKeys)); + this.masterKeys = unmodifiableList(new ArrayList<>(masterKeys)); + return this; + } + + public KeyringTrace getKeyringTrace() { + return keyringTrace; + } + + public Builder setKeyringTrace(KeyringTrace keyringTrace) { + this.keyringTrace = keyringTrace; return this; } } diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyringTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyringTest.java index 6ed3629ff..30ba8ba41 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyringTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/KmsKeyringTest.java @@ -21,6 +21,8 @@ import com.amazonaws.encryptionsdk.exception.MismatchedDataKeyException; import com.amazonaws.encryptionsdk.kms.DataKeyEncryptionDao; import com.amazonaws.encryptionsdk.kms.DataKeyEncryptionDao.DecryptDataKeyResult; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import com.amazonaws.encryptionsdk.model.KeyBlob; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -41,6 +43,7 @@ import static com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag.GENERATED_DATA_KEY; import static com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT; import static com.amazonaws.encryptionsdk.kms.KmsUtils.KMS_PROVIDER_ID; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -97,9 +100,10 @@ void testMalformedArns() { assertThrows(MalformedArnException.class, () -> new KmsKeyring(dataKeyEncryptionDao, null, "badArn")); assertThrows(MalformedArnException.class, () -> new KmsKeyring(dataKeyEncryptionDao, Collections.singletonList("badArn"), GENERATOR_KEY_ID)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); List encryptedDataKeys = new ArrayList<>(); @@ -107,7 +111,7 @@ void testMalformedArns() { encryptedDataKeys.add(ENCRYPTED_KEY_1); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getCleartextDataKey()); // Malformed Arn for a non KMS provider shouldn't fail encryptedDataKeys.clear(); @@ -122,26 +126,28 @@ void testGeneratorKeyInKeyIds() { @Test void testEncryptDecryptExistingDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setCleartextDataKey(PLAINTEXT_DATA_KEY) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onEncrypt(encryptionMaterials); assertEquals(3, encryptionMaterials.getEncryptedDataKeys().size()); - assertTrue(encryptionMaterials.getEncryptedDataKeys().contains(ENCRYPTED_GENERATOR_KEY)); - assertTrue(encryptionMaterials.getEncryptedDataKeys().contains(ENCRYPTED_KEY_1)); - assertTrue(encryptionMaterials.getEncryptedDataKeys().contains(ENCRYPTED_KEY_2)); + assertEncryptedDataKeyEquals(ENCRYPTED_KEY_1, encryptionMaterials.getEncryptedDataKeys().get(0)); + assertEncryptedDataKeyEquals(ENCRYPTED_KEY_2, encryptionMaterials.getEncryptedDataKeys().get(1)); + assertEncryptedDataKeyEquals(ENCRYPTED_GENERATOR_KEY, encryptionMaterials.getEncryptedDataKeys().get(2)); assertEquals(3, encryptionMaterials.getKeyringTrace().getEntries().size()); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().contains(ENCRYPTED_GENERATOR_KEY_TRACE)); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().contains(ENCRYPTED_KEY_1_TRACE)); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().contains(ENCRYPTED_KEY_2_TRACE)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); List encryptedDataKeys = new ArrayList<>(); @@ -150,7 +156,7 @@ void testEncryptDecryptExistingDataKey() { encryptedDataKeys.add(ENCRYPTED_KEY_2); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getCleartextDataKey()); KeyringTraceEntry expectedKeyringTraceEntry = new KeyringTraceEntry(KMS_PROVIDER_ID, GENERATOR_KEY_ID, KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT); assertEquals(expectedKeyringTraceEntry, decryptionMaterials.getKeyringTrace().getEntries().get(0)); @@ -158,15 +164,16 @@ void testEncryptDecryptExistingDataKey() { @Test void testEncryptNullDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .keyringTrace(new KeyringTrace()) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setKeyringTrace(new KeyringTrace()) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); when(dataKeyEncryptionDao.generateDataKey(GENERATOR_KEY_ID, ALGORITHM_SUITE, ENCRYPTION_CONTEXT)).thenReturn(new DataKeyEncryptionDao.GenerateDataKeyResult(PLAINTEXT_DATA_KEY, ENCRYPTED_GENERATOR_KEY)); keyring.onEncrypt(encryptionMaterials); - assertEquals(PLAINTEXT_DATA_KEY, encryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, encryptionMaterials.getCleartextDataKey()); assertEquals(4, encryptionMaterials.getKeyringTrace().getEntries().size()); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().contains(GENERATED_DATA_KEY_TRACE)); @@ -174,9 +181,10 @@ void testEncryptNullDataKey() { assertTrue(encryptionMaterials.getKeyringTrace().getEntries().contains(ENCRYPTED_KEY_1_TRACE)); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().contains(ENCRYPTED_KEY_2_TRACE)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); List encryptedDataKeys = new ArrayList<>(); @@ -185,7 +193,7 @@ void testEncryptNullDataKey() { encryptedDataKeys.add(ENCRYPTED_KEY_2); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getCleartextDataKey()); KeyringTraceEntry expectedKeyringTraceEntry = new KeyringTraceEntry(KMS_PROVIDER_ID, GENERATOR_KEY_ID, KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT); assertEquals(expectedKeyringTraceEntry, decryptionMaterials.getKeyringTrace().getEntries().get(0)); @@ -193,10 +201,11 @@ void testEncryptNullDataKey() { @Test void testEncryptNullGenerator() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .keyringTrace(new KeyringTrace()) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setKeyringTrace(new KeyringTrace()) + .setCleartextDataKey(PLAINTEXT_DATA_KEY) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); Keyring keyring = new KmsKeyring(dataKeyEncryptionDao, Collections.singletonList(KEY_ID_1), null); @@ -204,9 +213,9 @@ void testEncryptNullGenerator() { keyring.onEncrypt(encryptionMaterials); assertEquals(1, encryptionMaterials.getEncryptedDataKeys().size()); - assertTrue(encryptionMaterials.getEncryptedDataKeys().contains(ENCRYPTED_KEY_1)); + assertEncryptedDataKeyEquals(ENCRYPTED_KEY_1, encryptionMaterials.getEncryptedDataKeys().get(0)); - assertEquals(PLAINTEXT_DATA_KEY, encryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, encryptionMaterials.getCleartextDataKey()); assertEquals(1, encryptionMaterials.getKeyringTrace().getEntries().size()); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().contains(ENCRYPTED_KEY_1_TRACE)); @@ -216,30 +225,32 @@ void testEncryptNullGenerator() { void testDiscoveryEncrypt() { keyring = new KmsKeyring(dataKeyEncryptionDao, null, null); - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onEncrypt(encryptionMaterials); - assertFalse(encryptionMaterials.hasPlaintextDataKey()); + assertFalse(encryptionMaterials.hasCleartextDataKey()); assertEquals(0, encryptionMaterials.getKeyringTrace().getEntries().size()); } @Test - void testEncryptNoGeneratorOrPlaintextDataKey() { + void testEncryptNoGeneratorOrCleartextDataKey() { List keyIds = new ArrayList<>(); keyIds.add(KEY_ID_1); keyring = new KmsKeyring(dataKeyEncryptionDao, keyIds, null); - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE).build(); + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder().setAlgorithm(ALGORITHM_SUITE).build(); assertThrows(AwsCryptoException.class, () -> keyring.onEncrypt(encryptionMaterials)); } @Test void testDecryptFirstKeyFails() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); when(dataKeyEncryptionDao.decryptDataKey(ENCRYPTED_KEY_1, ALGORITHM_SUITE, ENCRYPTION_CONTEXT)).thenThrow(new CannotUnwrapDataKeyException()); @@ -249,7 +260,7 @@ void testDecryptFirstKeyFails() { encryptedDataKeys.add(ENCRYPTED_KEY_2); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getCleartextDataKey()); KeyringTraceEntry expectedKeyringTraceEntry = new KeyringTraceEntry(KMS_PROVIDER_ID, KEY_ID_2, KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT); assertEquals(expectedKeyringTraceEntry, decryptionMaterials.getKeyringTrace().getEntries().get(0)); @@ -257,8 +268,9 @@ void testDecryptFirstKeyFails() { @Test void testDecryptMismatchedDataKeyException() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); when(dataKeyEncryptionDao.decryptDataKey(ENCRYPTED_KEY_1, ALGORITHM_SUITE, ENCRYPTION_CONTEXT)).thenThrow(new MismatchedDataKeyException()); @@ -268,9 +280,10 @@ void testDecryptMismatchedDataKeyException() { @Test void testDecryptFirstKeyWrongProvider() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); EncryptedDataKey wrongProviderKey = new KeyBlob("OtherProvider", KEY_ID_1.getBytes(PROVIDER_ENCODING), new byte[]{}); @@ -280,7 +293,7 @@ void testDecryptFirstKeyWrongProvider() { encryptedDataKeys.add(ENCRYPTED_KEY_2); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getCleartextDataKey()); KeyringTraceEntry expectedKeyringTraceEntry = new KeyringTraceEntry(KMS_PROVIDER_ID, KEY_ID_2, KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT); assertEquals(expectedKeyringTraceEntry, decryptionMaterials.getKeyringTrace().getEntries().get(0)); @@ -290,9 +303,10 @@ void testDecryptFirstKeyWrongProvider() { void testDiscoveryDecrypt() { keyring = new KmsKeyring(dataKeyEncryptionDao, null, null); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); List encryptedDataKeys = new ArrayList<>(); @@ -300,7 +314,7 @@ void testDiscoveryDecrypt() { encryptedDataKeys.add(ENCRYPTED_KEY_2); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getCleartextDataKey()); KeyringTraceEntry expectedKeyringTraceEntry = new KeyringTraceEntry(KMS_PROVIDER_ID, KEY_ID_1, KeyringTraceFlag.DECRYPTED_DATA_KEY, KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT); assertEquals(expectedKeyringTraceEntry, decryptionMaterials.getKeyringTrace().getEntries().get(0)); @@ -308,27 +322,35 @@ void testDiscoveryDecrypt() { @Test void testDecryptAlreadyDecryptedDataKey() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .encryptionContext(ENCRYPTION_CONTEXT) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setCleartextDataKey(PLAINTEXT_DATA_KEY) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onDecrypt(decryptionMaterials, Collections.singletonList(ENCRYPTED_GENERATOR_KEY)); - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getCleartextDataKey()); assertEquals(0, decryptionMaterials.getKeyringTrace().getEntries().size()); } @Test void testDecryptNoDataKey() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, Collections.emptyList()); - assertFalse(decryptionMaterials.hasPlaintextDataKey()); + assertFalse(decryptionMaterials.hasCleartextDataKey()); assertEquals(0, decryptionMaterials.getKeyringTrace().getEntries().size()); } + + private void assertEncryptedDataKeyEquals(EncryptedDataKey expected, EncryptedDataKey actual) { + assertEquals(expected.getProviderId(), actual.getProviderId()); + assertArrayEquals(expected.getProviderInformation(), actual.getProviderInformation()); + assertArrayEquals(expected.getEncryptedDataKey(), actual.getEncryptedDataKey()); + } } diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderKeyringTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderKeyringTest.java deleted file mode 100644 index 64b8b26dd..000000000 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MasterKeyProviderKeyringTest.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except - * in compliance with the License. A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file 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.amazonaws.encryptionsdk.keyrings; - -import com.amazonaws.encryptionsdk.CryptoAlgorithm; -import com.amazonaws.encryptionsdk.DataKey; -import com.amazonaws.encryptionsdk.EncryptedDataKey; -import com.amazonaws.encryptionsdk.MasterKey; -import com.amazonaws.encryptionsdk.MasterKeyProvider; -import com.amazonaws.encryptionsdk.MasterKeyRequest; -import com.amazonaws.encryptionsdk.exception.AwsCryptoException; -import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException; -import com.amazonaws.encryptionsdk.jce.JceMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKey; -import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider; -import com.amazonaws.encryptionsdk.model.KeyBlob; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static com.amazonaws.encryptionsdk.EncryptedDataKey.PROVIDER_ENCODING; -import static com.amazonaws.encryptionsdk.internal.RandomBytesGenerator.generate; -import static com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag.DECRYPTED_DATA_KEY; -import static com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag.ENCRYPTED_DATA_KEY; -import static com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag.GENERATED_DATA_KEY; -import static com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT; -import static com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag.VERIFIED_ENCRYPTION_CONTEXT; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class MasterKeyProviderKeyringTest { - - private static final CryptoAlgorithm ALGORITHM_SUITE = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256; - private static final SecretKey PLAINTEXT_DATA_KEY = new SecretKeySpec(generate(ALGORITHM_SUITE.getDataKeyLength()), ALGORITHM_SUITE.getDataKeyAlgo()); - private static final Map ENCRYPTION_CONTEXT = Collections.singletonMap("myKey", "myValue"); - - @Test - void testOnEncryptWithoutPlaintextDataKey() { - - MasterKeyProvider masterKeyProvider = mock(JceMasterKey.class); - - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .build(); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - - JceMasterKey masterKey1 = mock(JceMasterKey.class); - JceMasterKey masterKey2 = mock(JceMasterKey.class); - - List masterKeys = new ArrayList<>(); - masterKeys.add(masterKey1); - masterKeys.add(masterKey2); - - ArgumentCaptor masterKeyRequestCaptor = ArgumentCaptor.forClass(MasterKeyRequest.class); - ArgumentCaptor dataKeyCaptor = ArgumentCaptor.forClass(DataKey.class); - - final String KEY_ID_1 = "KeyId1"; - final String KEY_ID_2 = "KeyId2"; - final String PROVIDER_1 = "Provider1"; - final String PROVIDER_2 = "Provider2"; - - DataKey dataKey1 = new DataKey<>(PLAINTEXT_DATA_KEY, generate(100), KEY_ID_1.getBytes(PROVIDER_ENCODING), masterKey1); - DataKey dataKey2 = new DataKey<>(PLAINTEXT_DATA_KEY, generate(100), KEY_ID_2.getBytes(PROVIDER_ENCODING), masterKey2); - - when(masterKeyProvider.getMasterKeysForEncryption(masterKeyRequestCaptor.capture())).thenReturn(masterKeys); - when(masterKey1.generateDataKey(ALGORITHM_SUITE, ENCRYPTION_CONTEXT)).thenReturn(dataKey1); - when(masterKey2.encryptDataKey(eq(ALGORITHM_SUITE), eq(ENCRYPTION_CONTEXT), dataKeyCaptor.capture())) - .thenReturn(dataKey2); - when(masterKey1.getProviderId()).thenReturn(PROVIDER_1); - when(masterKey1.getKeyId()).thenReturn(KEY_ID_1); - when(masterKey2.getProviderId()).thenReturn(PROVIDER_2); - when(masterKey2.getKeyId()).thenReturn(KEY_ID_2); - when(masterKey1.isEncryptionContextSigned()).thenReturn(true); - when(masterKey2.isEncryptionContextSigned()).thenReturn(false); - - keyring.onEncrypt(encryptionMaterials); - - assertEquals(ENCRYPTION_CONTEXT, masterKeyRequestCaptor.getValue().getEncryptionContext()); - assertEquals(PLAINTEXT_DATA_KEY, dataKeyCaptor.getValue().getKey()); - assertEncryptedDataKeyEquals(dataKey1, encryptionMaterials.getEncryptedDataKeys().get(0)); - assertEncryptedDataKeyEquals(dataKey2, encryptionMaterials.getEncryptedDataKeys().get(1)); - assertEquals(new KeyringTraceEntry(PROVIDER_1, KEY_ID_1, GENERATED_DATA_KEY), - encryptionMaterials.getKeyringTrace().getEntries().get(0)); - assertEquals(new KeyringTraceEntry(PROVIDER_1, KEY_ID_1, ENCRYPTED_DATA_KEY, SIGNED_ENCRYPTION_CONTEXT), - encryptionMaterials.getKeyringTrace().getEntries().get(1)); - assertEquals(new KeyringTraceEntry(PROVIDER_2, KEY_ID_2, ENCRYPTED_DATA_KEY), - encryptionMaterials.getKeyringTrace().getEntries().get(2)); - } - - @Test - void testOnEncryptWithPlaintextDataKey() { - - MasterKeyProvider masterKeyProvider = mock(KmsMasterKeyProvider.class); - - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .build(); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - - KmsMasterKey masterKey1 = mock(KmsMasterKey.class); - KmsMasterKey masterKey2 = mock(KmsMasterKey.class); - - List masterKeys = new ArrayList<>(); - masterKeys.add(masterKey1); - masterKeys.add(masterKey2); - - ArgumentCaptor masterKeyRequestCaptor = ArgumentCaptor.forClass(MasterKeyRequest.class); - ArgumentCaptor dataKeyCaptor = ArgumentCaptor.forClass(DataKey.class); - - final String KEY_ID_1 = "KeyId1"; - final String KEY_ID_2 = "KeyId2"; - final String PROVIDER_1 = "Provider1"; - final String PROVIDER_2 = "Provider2"; - - DataKey dataKey1 = new DataKey<>(PLAINTEXT_DATA_KEY, generate(100), KEY_ID_1.getBytes(PROVIDER_ENCODING), masterKey1); - DataKey dataKey2 = new DataKey<>(PLAINTEXT_DATA_KEY, generate(100), KEY_ID_2.getBytes(PROVIDER_ENCODING), masterKey2); - - when(masterKeyProvider.getMasterKeysForEncryption(masterKeyRequestCaptor.capture())).thenReturn(masterKeys); - when(masterKey1.encryptDataKey(eq(ALGORITHM_SUITE), eq(ENCRYPTION_CONTEXT), dataKeyCaptor.capture())) - .thenReturn(dataKey1); - when(masterKey2.encryptDataKey(eq(ALGORITHM_SUITE), eq(ENCRYPTION_CONTEXT), dataKeyCaptor.capture())) - .thenReturn(dataKey2); - when(masterKey1.getProviderId()).thenReturn(PROVIDER_1); - when(masterKey1.getKeyId()).thenReturn(KEY_ID_1); - when(masterKey2.getProviderId()).thenReturn(PROVIDER_2); - when(masterKey2.getKeyId()).thenReturn(KEY_ID_2); - - keyring.onEncrypt(encryptionMaterials); - - assertEquals(ENCRYPTION_CONTEXT, masterKeyRequestCaptor.getValue().getEncryptionContext()); - assertEquals(PLAINTEXT_DATA_KEY, dataKeyCaptor.getAllValues().get(0).getKey()); - assertEquals(PLAINTEXT_DATA_KEY, dataKeyCaptor.getAllValues().get(1).getKey()); - assertEncryptedDataKeyEquals(dataKey1, encryptionMaterials.getEncryptedDataKeys().get(0)); - assertEncryptedDataKeyEquals(dataKey2, encryptionMaterials.getEncryptedDataKeys().get(1)); - assertEquals(new KeyringTraceEntry(PROVIDER_1, KEY_ID_1, ENCRYPTED_DATA_KEY, SIGNED_ENCRYPTION_CONTEXT), - encryptionMaterials.getKeyringTrace().getEntries().get(0)); - assertEquals(new KeyringTraceEntry(PROVIDER_2, KEY_ID_2, ENCRYPTED_DATA_KEY, SIGNED_ENCRYPTION_CONTEXT), - encryptionMaterials.getKeyringTrace().getEntries().get(1)); - } - - @SuppressWarnings("unchecked") - @Test - void testOnEncryptWithNonKmsOrJceMasterKeyProvider() { - - MasterKeyProvider masterKeyProvider = mock(MasterKeyProvider.class); - - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .build(); - - Keyring keyring = new MasterKeyProviderKeyring(masterKeyProvider); - - MasterKey masterKey = mock(MasterKey.class); - - final String KEY_ID = "KeyId1"; - final String PROVIDER = "Provider1"; - - DataKey dataKey = new DataKey(PLAINTEXT_DATA_KEY, generate(100), KEY_ID.getBytes(PROVIDER_ENCODING), masterKey); - - when(masterKeyProvider.getMasterKeysForEncryption(isA(MasterKeyRequest.class))).thenReturn(singletonList(masterKey)); - when(masterKey.encryptDataKey(eq(ALGORITHM_SUITE), eq(ENCRYPTION_CONTEXT), isA(DataKey.class))) - .thenReturn(dataKey); - when(masterKey.getProviderId()).thenReturn(PROVIDER); - when(masterKey.getKeyId()).thenReturn(KEY_ID); - - keyring.onEncrypt(encryptionMaterials); - - assertEncryptedDataKeyEquals(dataKey, encryptionMaterials.getEncryptedDataKeys().get(0)); - assertEquals(new KeyringTraceEntry(PROVIDER, KEY_ID, ENCRYPTED_DATA_KEY), - encryptionMaterials.getKeyringTrace().getEntries().get(0)); - } - - @Test - void testOnEncryptWithNoMasterKeys() { - MasterKeyProvider masterKeyProvider = mock(KmsMasterKeyProvider.class); - - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .build(); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - - when(masterKeyProvider.getMasterKeysForEncryption(isA(MasterKeyRequest.class))).thenReturn(emptyList()); - - assertThrows(AwsCryptoException.class, () -> keyring.onEncrypt(encryptionMaterials)); - } - - @Test - void testOnDecryptWithPlaintextDataKey() { - MasterKeyProvider masterKeyProvider = mock(KmsMasterKeyProvider.class); - - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .build(); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - keyring.onDecrypt(decryptionMaterials, emptyList()); - - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); - } - - @Test - void testOnDecrypt() { - MasterKeyProvider masterKeyProvider = mock(KmsMasterKeyProvider.class); - KmsMasterKey masterKey = mock(KmsMasterKey.class); - - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .build(); - - final String KEY_ID = "KeyId1"; - final String PROVIDER = "Provider1"; - - EncryptedDataKey encryptedDataKey = new KeyBlob(PROVIDER, - KEY_ID.getBytes(PROVIDER_ENCODING), generate(ALGORITHM_SUITE.getDataKeyLength())); - - when(masterKeyProvider.decryptDataKey(ALGORITHM_SUITE, singletonList(encryptedDataKey), ENCRYPTION_CONTEXT)) - .thenReturn(new DataKey<>(PLAINTEXT_DATA_KEY, encryptedDataKey.getEncryptedDataKey(), - encryptedDataKey.getProviderInformation(), masterKey)); - when(masterKey.getProviderId()).thenReturn(PROVIDER); - when(masterKey.getKeyId()).thenReturn(KEY_ID); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - keyring.onDecrypt(decryptionMaterials, singletonList(encryptedDataKey)); - - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); - assertEquals(new KeyringTraceEntry(PROVIDER, KEY_ID, DECRYPTED_DATA_KEY, VERIFIED_ENCRYPTION_CONTEXT), - decryptionMaterials.getKeyringTrace().getEntries().get(0)); - } - - @Test - void testOnDecryptMasterKeyCannotUnwrapDataKeyException() { - MasterKeyProvider masterKeyProvider = mock(KmsMasterKeyProvider.class); - - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .build(); - - EncryptedDataKey encryptedDataKey = mock(EncryptedDataKey.class); - - when(masterKeyProvider.decryptDataKey(ALGORITHM_SUITE, singletonList(encryptedDataKey), ENCRYPTION_CONTEXT)) - .thenThrow(new CannotUnwrapDataKeyException()); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - keyring.onDecrypt(decryptionMaterials, singletonList(encryptedDataKey)); - - assertFalse(decryptionMaterials.hasPlaintextDataKey()); - } - - @Test - void testOnDecryptMasterKeyOtherException() { - MasterKeyProvider masterKeyProvider = mock(KmsMasterKeyProvider.class); - - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .build(); - - EncryptedDataKey encryptedDataKey = mock(EncryptedDataKey.class); - - when(masterKeyProvider.decryptDataKey(ALGORITHM_SUITE, singletonList(encryptedDataKey), ENCRYPTION_CONTEXT)) - .thenThrow(new AwsCryptoException()); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - assertThrows(AwsCryptoException.class, () -> keyring.onDecrypt(decryptionMaterials, singletonList(encryptedDataKey))); - } - - @Test - void testOnDecryptNonVerifiedEncryptionContext() { - MasterKeyProvider masterKeyProvider = mock(JceMasterKey.class); - JceMasterKey masterKey = mock(JceMasterKey.class); - - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .build(); - - final String KEY_ID = "KeyId1"; - final String PROVIDER = "Provider1"; - - EncryptedDataKey encryptedDataKey = new KeyBlob(PROVIDER, - KEY_ID.getBytes(PROVIDER_ENCODING), generate(ALGORITHM_SUITE.getDataKeyLength())); - - when(masterKeyProvider.decryptDataKey(ALGORITHM_SUITE, singletonList(encryptedDataKey), ENCRYPTION_CONTEXT)) - .thenReturn(new DataKey<>(PLAINTEXT_DATA_KEY, encryptedDataKey.getEncryptedDataKey(), - encryptedDataKey.getProviderInformation(), masterKey)); - when(masterKey.getProviderId()).thenReturn(PROVIDER); - when(masterKey.getKeyId()).thenReturn(KEY_ID); - when(masterKey.isEncryptionContextSigned()).thenReturn(false); - - Keyring keyring = StandardKeyrings.masterKeyProvider(masterKeyProvider); - keyring.onDecrypt(decryptionMaterials, singletonList(encryptedDataKey)); - - assertEquals(PLAINTEXT_DATA_KEY, decryptionMaterials.getPlaintextDataKey()); - assertEquals(new KeyringTraceEntry(PROVIDER, KEY_ID, DECRYPTED_DATA_KEY), - decryptionMaterials.getKeyringTrace().getEntries().get(0)); - } - - private static void assertEncryptedDataKeyEquals(EncryptedDataKey expected, EncryptedDataKey actual) { - assertEquals(expected.getProviderId(), actual.getProviderId()); - assertArrayEquals(expected.getProviderInformation(), actual.getProviderInformation()); - assertArrayEquals(expected.getEncryptedDataKey(), actual.getEncryptedDataKey()); - } -} diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyringTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyringTest.java index 75e43a676..a9d414754 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyringTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/MultiKeyringTest.java @@ -15,6 +15,8 @@ import com.amazonaws.encryptionsdk.EncryptedDataKey; import com.amazonaws.encryptionsdk.exception.AwsCryptoException; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -22,6 +24,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import javax.crypto.SecretKey; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -44,6 +47,7 @@ class MultiKeyringTest { @Mock EncryptionMaterials encryptionMaterials; @Mock DecryptionMaterials decryptionMaterials; @Mock List encryptedDataKeys; + @Mock SecretKey cleartextDataKey; final List childrenKeyrings = new ArrayList<>(); @BeforeEach @@ -63,7 +67,7 @@ void testConstructor() { @Test void testOnEncryptWithGenerator() { MultiKeyring keyring = new MultiKeyring(generatorKeyring, childrenKeyrings); - when(encryptionMaterials.hasPlaintextDataKey()).thenReturn(true); + when(encryptionMaterials.hasCleartextDataKey()).thenReturn(true); keyring.onEncrypt(encryptionMaterials); @@ -75,7 +79,7 @@ void testOnEncryptWithGenerator() { @Test void testOnEncryptWithoutGenerator() { MultiKeyring keyring = new MultiKeyring(null, childrenKeyrings); - when(encryptionMaterials.hasPlaintextDataKey()).thenReturn(true); + when(encryptionMaterials.hasCleartextDataKey()).thenReturn(true); keyring.onEncrypt(encryptionMaterials); @@ -87,7 +91,7 @@ void testOnEncryptWithoutGenerator() { @Test void testOnEncryptNoPlaintextDataKey() { MultiKeyring keyring = new MultiKeyring(null, childrenKeyrings); - when(encryptionMaterials.hasPlaintextDataKey()).thenReturn(false); + when(encryptionMaterials.hasCleartextDataKey()).thenReturn(false); assertThrows(AwsCryptoException.class, () -> keyring.onEncrypt(encryptionMaterials)); } @@ -96,7 +100,7 @@ void testOnEncryptNoPlaintextDataKey() { void testOnDecryptWithPlaintextDataKey() { MultiKeyring keyring = new MultiKeyring(generatorKeyring, childrenKeyrings); - when(decryptionMaterials.hasPlaintextDataKey()).thenReturn(true); + when(decryptionMaterials.hasCleartextDataKey()).thenReturn(true); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); verifyNoInteractions(generatorKeyring, keyring1, keyring2); @@ -106,7 +110,7 @@ void testOnDecryptWithPlaintextDataKey() { void testOnDecryptWithGenerator() { MultiKeyring keyring = new MultiKeyring(generatorKeyring, childrenKeyrings); - when(decryptionMaterials.hasPlaintextDataKey()).thenReturn(false).thenReturn(false).thenReturn(true); + when(decryptionMaterials.hasCleartextDataKey()).thenReturn(false).thenReturn(false).thenReturn(true); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); InOrder inOrder = inOrder(generatorKeyring, keyring1); @@ -119,7 +123,7 @@ void testOnDecryptWithGenerator() { void testOnDecryptWithoutGenerator() { MultiKeyring keyring = new MultiKeyring(null, childrenKeyrings); - when(decryptionMaterials.hasPlaintextDataKey()).thenReturn(false).thenReturn(false).thenReturn(true); + when(decryptionMaterials.hasCleartextDataKey()).thenReturn(false).thenReturn(false).thenReturn(true); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); InOrder inOrder = inOrder(keyring1, keyring2); @@ -132,7 +136,7 @@ void testOnDecryptWithoutGenerator() { void testOnDecryptFailureThenSuccess() { MultiKeyring keyring = new MultiKeyring(generatorKeyring, childrenKeyrings); - when(decryptionMaterials.hasPlaintextDataKey()).thenReturn(false).thenReturn(true); + when(decryptionMaterials.hasCleartextDataKey()).thenReturn(false).thenReturn(true); doThrow(new IllegalStateException()).when(generatorKeyring).onDecrypt(decryptionMaterials, encryptedDataKeys); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); @@ -147,7 +151,7 @@ void testOnDecryptFailureThenSuccess() { void testOnDecryptFailure() { MultiKeyring keyring = new MultiKeyring(generatorKeyring, childrenKeyrings); - when(decryptionMaterials.hasPlaintextDataKey()).thenReturn(false); + when(decryptionMaterials.hasCleartextDataKey()).thenReturn(false); doThrow(new AwsCryptoException()).when(generatorKeyring).onDecrypt(decryptionMaterials, encryptedDataKeys); doThrow(new IllegalStateException()).when(keyring1).onDecrypt(decryptionMaterials, encryptedDataKeys); doThrow(new IllegalArgumentException()).when(keyring2).onDecrypt(decryptionMaterials, encryptedDataKeys); @@ -172,7 +176,7 @@ void testOnDecryptFailure() { void testOnDecryptNoFailuresNoPlaintextDataKeys() { MultiKeyring keyring = new MultiKeyring(generatorKeyring, childrenKeyrings); - when(decryptionMaterials.hasPlaintextDataKey()).thenReturn(false, false, false, false); + when(decryptionMaterials.hasCleartextDataKey()).thenReturn(false, false, false, false); keyring.onDecrypt(decryptionMaterials, encryptedDataKeys); InOrder inOrder = inOrder(generatorKeyring, keyring1, keyring2); diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawAesKeyringTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawAesKeyringTest.java index 4183e9a06..556e63132 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawAesKeyringTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawAesKeyringTest.java @@ -15,6 +15,8 @@ import com.amazonaws.encryptionsdk.EncryptedDataKey; import com.amazonaws.encryptionsdk.internal.Utils; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import com.amazonaws.encryptionsdk.model.KeyBlob; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.Test; @@ -53,10 +55,11 @@ void testValidToDecrypt() { @Test void testEncryptDecryptExistingDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM) - .plaintextDataKey(DATA_KEY) - .keyringTrace(new KeyringTrace()) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setCleartextDataKey(DATA_KEY) + .setKeyringTrace(new KeyringTrace()) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onEncrypt(encryptionMaterials); @@ -75,14 +78,15 @@ void testEncryptDecryptExistingDataKey() { assertTrue(encryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().contains(KeyringTraceFlag.ENCRYPTED_DATA_KEY)); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().contains(KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, encryptionMaterials.getEncryptedDataKeys()); - assertEquals(DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(DATA_KEY, decryptionMaterials.getCleartextDataKey()); assertEquals(KEYNAME, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyName()); assertEquals(KEYNAMESPACE, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyNamespace()); assertEquals(2, decryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().size()); @@ -92,15 +96,16 @@ void testEncryptDecryptExistingDataKey() { @Test void testEncryptDecryptGenerateDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM) - .keyringTrace(new KeyringTrace()) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setKeyringTrace(new KeyringTrace()) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onEncrypt(encryptionMaterials); - assertNotNull(encryptionMaterials.getPlaintextDataKey()); - assertEquals(encryptionMaterials.getPlaintextDataKey().getAlgorithm(), ALGORITHM.getDataKeyAlgo()); + assertNotNull(encryptionMaterials.getCleartextDataKey()); + assertEquals(encryptionMaterials.getCleartextDataKey().getAlgorithm(), ALGORITHM.getDataKeyAlgo()); assertEquals(1, encryptionMaterials.getEncryptedDataKeys().size()); final EncryptedDataKey actualEncryptedDataKey = encryptionMaterials.getEncryptedDataKeys().get(0); @@ -115,14 +120,15 @@ void testEncryptDecryptGenerateDataKey() { assertTrue(encryptionMaterials.getKeyringTrace().getEntries().get(1).getFlags().contains(KeyringTraceFlag.ENCRYPTED_DATA_KEY)); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().get(1).getFlags().contains(KeyringTraceFlag.SIGNED_ENCRYPTION_CONTEXT)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, encryptionMaterials.getEncryptedDataKeys()); - assertEquals(encryptionMaterials.getPlaintextDataKey(), decryptionMaterials.getPlaintextDataKey()); + assertEquals(encryptionMaterials.getCleartextDataKey(), decryptionMaterials.getCleartextDataKey()); assertEquals(KEYNAME, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyName()); assertEquals(KEYNAMESPACE, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyNamespace()); assertEquals(2, decryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().size()); diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawKeyringTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawKeyringTest.java index 3fe1fb416..60482d403 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawKeyringTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawKeyringTest.java @@ -16,6 +16,8 @@ import com.amazonaws.encryptionsdk.CryptoAlgorithm; import com.amazonaws.encryptionsdk.EncryptedDataKey; import com.amazonaws.encryptionsdk.internal.JceKeyCipher; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import com.amazonaws.encryptionsdk.model.KeyBlob; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -71,10 +73,11 @@ boolean validToDecrypt(EncryptedDataKey encryptedDataKey) { @Test void testEncryptDecryptExistingDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM) - .plaintextDataKey(DATA_KEY) - .keyringTrace(new KeyringTrace()) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setCleartextDataKey(DATA_KEY) + .setKeyringTrace(new KeyringTrace()) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onEncrypt(encryptionMaterials); @@ -84,32 +87,34 @@ void testEncryptDecryptExistingDataKey() { assertEquals(1, encryptionMaterials.getKeyringTrace().getEntries().size()); assertEquals(ENCRYPTED_DATA_KEY_TRACE, encryptionMaterials.getKeyringTrace().getEntries().get(0)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, Collections.singletonList(ENCRYPTED_DATA_KEY)); - assertEquals(DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(DATA_KEY, decryptionMaterials.getCleartextDataKey()); assertEquals(DECRYPTED_DATA_KEY_TRACE, decryptionMaterials.getKeyringTrace().getEntries().get(0)); } @Test void testEncryptNullDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM) - .keyringTrace(new KeyringTrace()) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setKeyringTrace(new KeyringTrace()) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); ArgumentCaptor dataKeyCaptor = ArgumentCaptor.forClass(byte[].class); when(jceKeyCipher.encryptKey(dataKeyCaptor.capture(), eq(KEYNAME), eq(KEYNAMESPACE), eq(ENCRYPTION_CONTEXT))).thenReturn(ENCRYPTED_DATA_KEY); keyring.onEncrypt(encryptionMaterials); - assertEquals(encryptionMaterials.getPlaintextDataKey().getAlgorithm(), ALGORITHM.getDataKeyAlgo()); - assertArrayEquals(encryptionMaterials.getPlaintextDataKey().getEncoded(), dataKeyCaptor.getValue()); + assertEquals(encryptionMaterials.getCleartextDataKey().getAlgorithm(), ALGORITHM.getDataKeyAlgo()); + assertArrayEquals(encryptionMaterials.getCleartextDataKey().getEncoded(), dataKeyCaptor.getValue()); assertEquals(1, encryptionMaterials.getEncryptedDataKeys().size()); - assertNotNull(encryptionMaterials.getPlaintextDataKey()); + assertTrue(encryptionMaterials.hasCleartextDataKey()); assertEncryptedDataKeyEquals(ENCRYPTED_DATA_KEY, encryptionMaterials.getEncryptedDataKeys().get(0)); assertEquals(2, encryptionMaterials.getKeyringTrace().getEntries().size()); assertEquals(GENERATED_DATA_KEY_TRACE, encryptionMaterials.getKeyringTrace().getEntries().get(0)); @@ -118,50 +123,54 @@ void testEncryptNullDataKey() { @Test void testDecryptAlreadyDecryptedDataKey() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .plaintextDataKey(DATA_KEY) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setCleartextDataKey(DATA_KEY) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, Collections.singletonList(ENCRYPTED_DATA_KEY)); - assertEquals(DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(DATA_KEY, decryptionMaterials.getCleartextDataKey()); assertEquals(0, decryptionMaterials.getKeyringTrace().getEntries().size()); } @Test void testDecryptNoValidDataKey() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, Collections.singletonList(INVALID_DATA_KEY)); - assertFalse(decryptionMaterials.hasPlaintextDataKey()); + assertFalse(decryptionMaterials.hasCleartextDataKey()); assertEquals(0, decryptionMaterials.getKeyringTrace().getEntries().size()); } @Test void testDecryptNoDataKey() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, Collections.emptyList()); - assertFalse(decryptionMaterials.hasPlaintextDataKey()); + assertFalse(decryptionMaterials.hasCleartextDataKey()); assertEquals(0, decryptionMaterials.getKeyringTrace().getEntries().size()); } @Test void testDecryptMultipleKeysOneInvalid() { - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); final List edks = new ArrayList<>(); @@ -170,7 +179,7 @@ void testDecryptMultipleKeysOneInvalid() { keyring.onDecrypt(decryptionMaterials, edks); - assertEquals(DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(DATA_KEY, decryptionMaterials.getCleartextDataKey()); assertEquals(DECRYPTED_DATA_KEY_TRACE, decryptionMaterials.getKeyringTrace().getEntries().get(0)); } @@ -178,9 +187,10 @@ void testDecryptMultipleKeysOneInvalid() { void testDecryptMultipleKeysOneException() throws GeneralSecurityException { final EncryptedDataKey BAD_DATA_KEY = new KeyBlob("exceptionProvider", new byte[]{1, 2, 3}, new byte[]{4, 5, 6}); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); when(jceKeyCipher.decryptKey(BAD_DATA_KEY, KEYNAME, ENCRYPTION_CONTEXT)) @@ -192,7 +202,7 @@ void testDecryptMultipleKeysOneException() throws GeneralSecurityException { keyring.onDecrypt(decryptionMaterials, edks); - assertEquals(DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(DATA_KEY, decryptionMaterials.getCleartextDataKey()); assertEquals(DECRYPTED_DATA_KEY_TRACE, decryptionMaterials.getKeyringTrace().getEntries().get(0)); } diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java index 6e43d5d37..1f3f1fe63 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/keyrings/RawRsaKeyringTest.java @@ -14,6 +14,8 @@ package com.amazonaws.encryptionsdk.keyrings; import com.amazonaws.encryptionsdk.EncryptedDataKey; +import com.amazonaws.encryptionsdk.model.DecryptionMaterials; +import com.amazonaws.encryptionsdk.model.EncryptionMaterials; import com.amazonaws.encryptionsdk.model.KeyBlob; import org.apache.commons.lang3.ArrayUtils; import org.junit.jupiter.api.BeforeAll; @@ -31,7 +33,6 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; class RawRsaKeyringTest { @@ -61,10 +62,11 @@ void testValidToDecrypt() { @Test void testEncryptDecryptExistingDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM) - .plaintextDataKey(DATA_KEY) - .keyringTrace(new KeyringTrace()) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setCleartextDataKey(DATA_KEY) + .setKeyringTrace(new KeyringTrace()) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onEncrypt(encryptionMaterials); @@ -81,14 +83,15 @@ void testEncryptDecryptExistingDataKey() { assertEquals(1, encryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().size()); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().contains(KeyringTraceFlag.ENCRYPTED_DATA_KEY)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, encryptionMaterials.getEncryptedDataKeys()); - assertEquals(DATA_KEY, decryptionMaterials.getPlaintextDataKey()); + assertEquals(DATA_KEY, decryptionMaterials.getCleartextDataKey()); assertEquals(KEYNAME, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyName()); assertEquals(KEYNAMESPACE, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyNamespace()); assertEquals(1, decryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().size()); @@ -97,15 +100,16 @@ void testEncryptDecryptExistingDataKey() { @Test void testEncryptDecryptGenerateDataKey() { - EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder(ALGORITHM) - .keyringTrace(new KeyringTrace()) - .encryptionContext(ENCRYPTION_CONTEXT) + EncryptionMaterials encryptionMaterials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setKeyringTrace(new KeyringTrace()) + .setEncryptionContext(ENCRYPTION_CONTEXT) .build(); keyring.onEncrypt(encryptionMaterials); - assertNotNull(encryptionMaterials.getPlaintextDataKey()); - assertEquals(encryptionMaterials.getPlaintextDataKey().getAlgorithm(), ALGORITHM.getDataKeyAlgo()); + assertTrue(encryptionMaterials.hasCleartextDataKey()); + assertEquals(encryptionMaterials.getCleartextDataKey().getAlgorithm(), ALGORITHM.getDataKeyAlgo()); assertEquals(1, encryptionMaterials.getEncryptedDataKeys().size()); final EncryptedDataKey actualEncryptedDataKey = encryptionMaterials.getEncryptedDataKeys().get(0); @@ -118,14 +122,15 @@ void testEncryptDecryptGenerateDataKey() { assertEquals(1, encryptionMaterials.getKeyringTrace().getEntries().get(1).getFlags().size()); assertTrue(encryptionMaterials.getKeyringTrace().getEntries().get(1).getFlags().contains(KeyringTraceFlag.ENCRYPTED_DATA_KEY)); - DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder(ALGORITHM) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(new KeyringTrace()) + DecryptionMaterials decryptionMaterials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(new KeyringTrace()) .build(); keyring.onDecrypt(decryptionMaterials, encryptionMaterials.getEncryptedDataKeys()); - assertEquals(encryptionMaterials.getPlaintextDataKey(), decryptionMaterials.getPlaintextDataKey()); + assertEquals(encryptionMaterials.getCleartextDataKey(), decryptionMaterials.getCleartextDataKey()); assertEquals(KEYNAME, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyName()); assertEquals(KEYNAMESPACE, decryptionMaterials.getKeyringTrace().getEntries().get(0).getKeyNamespace()); assertEquals(1, decryptionMaterials.getKeyringTrace().getEntries().get(0).getFlags().size()); diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/DecryptionMaterialsTest.java b/src/test/java/com/amazonaws/encryptionsdk/model/DecryptionMaterialsTest.java similarity index 60% rename from src/test/java/com/amazonaws/encryptionsdk/keyrings/DecryptionMaterialsTest.java rename to src/test/java/com/amazonaws/encryptionsdk/model/DecryptionMaterialsTest.java index 68687d4ad..444908478 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/DecryptionMaterialsTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/model/DecryptionMaterialsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except * in compliance with the License. A copy of the License is located at @@ -11,10 +11,13 @@ * specific language governing permissions and limitations under the License. */ -package com.amazonaws.encryptionsdk.keyrings; +package com.amazonaws.encryptionsdk.model; import com.amazonaws.encryptionsdk.CryptoAlgorithm; import com.amazonaws.encryptionsdk.internal.TrailingSignatureAlgorithm; +import com.amazonaws.encryptionsdk.keyrings.KeyringTrace; +import com.amazonaws.encryptionsdk.keyrings.KeyringTraceEntry; +import com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -28,8 +31,11 @@ import static com.amazonaws.encryptionsdk.internal.RandomBytesGenerator.generate; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; class DecryptionMaterialsTest { @@ -49,68 +55,47 @@ static void setup() throws Exception { VERIFICATION_KEY = keyPair.getPublic(); } - @Test - void testBuilderNullCryptoAlgorithm() { - assertThrows(NullPointerException.class, () -> DecryptionMaterials.newBuilder(null).build()); - } - @Test void testBuilder() { - DecryptionMaterials result = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(KEYRING_TRACE) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .verificationKey(VERIFICATION_KEY) + DecryptionMaterials result = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(KEYRING_TRACE) + .setCleartextDataKey(PLAINTEXT_DATA_KEY) + .setTrailingSignatureKey(VERIFICATION_KEY) .build(); - assertEquals(ALGORITHM_SUITE, result.getAlgorithmSuite()); + assertEquals(ALGORITHM_SUITE, result.getAlgorithm()); assertEquals(ENCRYPTION_CONTEXT, result.getEncryptionContext()); assertEquals(KEYRING_TRACE, result.getKeyringTrace()); - assertEquals(PLAINTEXT_DATA_KEY, result.getPlaintextDataKey()); - assertEquals(VERIFICATION_KEY, result.getVerificationKey()); + assertEquals(PLAINTEXT_DATA_KEY, result.getCleartextDataKey()); + assertEquals(VERIFICATION_KEY, result.getTrailingSignatureKey()); } @Test void testInvalidPlaintextDataKey() { SecretKey wrongLength = new SecretKeySpec(generate(ALGORITHM_SUITE.getDataKeyLength() + 1), ALGORITHM_SUITE.getDataKeyAlgo()); - assertThrows(IllegalArgumentException.class, () -> DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .plaintextDataKey(wrongLength) - .verificationKey(VERIFICATION_KEY) - .build()); - SecretKey wrongAlgorithm = new SecretKeySpec(generate(ALGORITHM_SUITE.getDataKeyLength()), "InvalidAlgorithm"); - assertThrows(IllegalArgumentException.class, () -> DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .plaintextDataKey(wrongAlgorithm) - .verificationKey(VERIFICATION_KEY) - .build()); - DecryptionMaterials materials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .verificationKey(VERIFICATION_KEY) + + DecryptionMaterials materials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setTrailingSignatureKey(VERIFICATION_KEY) .build(); assertThrows(IllegalArgumentException.class, () -> materials - .setPlaintextDataKey(wrongAlgorithm, KEYRING_TRACE_ENTRY)); + .setCleartextDataKey(wrongAlgorithm, KEYRING_TRACE_ENTRY)); assertThrows(IllegalArgumentException.class, () -> materials - .setPlaintextDataKey(wrongLength, KEYRING_TRACE_ENTRY)); - } - - @Test - void testInvalidVerificationKey() { - assertThrows(IllegalArgumentException.class, () -> DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .verificationKey(null) - .build()); - assertThrows(IllegalArgumentException.class, () -> DecryptionMaterials.newBuilder(CryptoAlgorithm.ALG_AES_128_GCM_IV12_TAG16_HKDF_SHA256) - .verificationKey(VERIFICATION_KEY) - .build()); - + .setCleartextDataKey(wrongLength, KEYRING_TRACE_ENTRY)); } @Test void testToBuilder() { - DecryptionMaterials expected = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(KEYRING_TRACE) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .verificationKey(VERIFICATION_KEY) + DecryptionMaterials expected = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(KEYRING_TRACE) + .setCleartextDataKey(PLAINTEXT_DATA_KEY) + .setTrailingSignatureKey(VERIFICATION_KEY) .build(); DecryptionMaterials actual = expected.toBuilder().build(); @@ -121,28 +106,34 @@ void testToBuilder() { @Test void testSetPlaintextDataKey() { - DecryptionMaterials materials = DecryptionMaterials.newBuilder(ALGORITHM_SUITE) - .verificationKey(VERIFICATION_KEY) + DecryptionMaterials materials = DecryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setTrailingSignatureKey(VERIFICATION_KEY) .build(); - assertThrows(NullPointerException.class, () -> materials.setPlaintextDataKey(null, KEYRING_TRACE_ENTRY)); - assertThrows(NullPointerException.class, () -> materials.setPlaintextDataKey(PLAINTEXT_DATA_KEY, null)); + assertThrows(NullPointerException.class, () -> materials.setCleartextDataKey(null, KEYRING_TRACE_ENTRY)); + assertThrows(NullPointerException.class, () -> materials.setCleartextDataKey(PLAINTEXT_DATA_KEY, null)); - materials.setPlaintextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY); - assertEquals(PLAINTEXT_DATA_KEY, materials.getPlaintextDataKey()); + materials.setCleartextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY); + assertEquals(PLAINTEXT_DATA_KEY, materials.getCleartextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, materials.getDataKey().getKey()); assertEquals(1, materials.getKeyringTrace().getEntries().size()); assertEquals(KEYRING_TRACE_ENTRY, materials.getKeyringTrace().getEntries().get(0)); - assertThrows(IllegalStateException.class, () -> materials.setPlaintextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY)); + assertThrows(IllegalStateException.class, () -> materials.setCleartextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY)); } @Test void testGetOptionalProperties() { - DecryptionMaterials materials = DecryptionMaterials.newBuilder(CryptoAlgorithm.ALG_AES_128_GCM_IV12_TAG16_HKDF_SHA256) - .build(); - - assertThrows(IllegalStateException.class, materials::getPlaintextDataKey); - assertThrows(IllegalStateException.class, materials::getVerificationKey); + DecryptionMaterials materials = DecryptionMaterials.newBuilder() + .build(); + + assertNull(materials.getAlgorithm()); + assertNull(materials.getCleartextDataKey()); + assertFalse(materials.hasCleartextDataKey()); + assertNull(materials.getTrailingSignatureKey()); + assertTrue(materials.getEncryptionContext().isEmpty()); + assertTrue(materials.getKeyringTrace().getEntries().isEmpty()); } } diff --git a/src/test/java/com/amazonaws/encryptionsdk/keyrings/EncryptionMaterialsTest.java b/src/test/java/com/amazonaws/encryptionsdk/model/EncryptionMaterialsTest.java similarity index 63% rename from src/test/java/com/amazonaws/encryptionsdk/keyrings/EncryptionMaterialsTest.java rename to src/test/java/com/amazonaws/encryptionsdk/model/EncryptionMaterialsTest.java index d1c207dbd..54c89ac59 100644 --- a/src/test/java/com/amazonaws/encryptionsdk/keyrings/EncryptionMaterialsTest.java +++ b/src/test/java/com/amazonaws/encryptionsdk/model/EncryptionMaterialsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except * in compliance with the License. A copy of the License is located at @@ -11,11 +11,13 @@ * specific language governing permissions and limitations under the License. */ -package com.amazonaws.encryptionsdk.keyrings; +package com.amazonaws.encryptionsdk.model; import com.amazonaws.encryptionsdk.CryptoAlgorithm; -import com.amazonaws.encryptionsdk.EncryptedDataKey; import com.amazonaws.encryptionsdk.internal.TrailingSignatureAlgorithm; +import com.amazonaws.encryptionsdk.keyrings.KeyringTrace; +import com.amazonaws.encryptionsdk.keyrings.KeyringTraceEntry; +import com.amazonaws.encryptionsdk.keyrings.KeyringTraceFlag; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -32,8 +34,11 @@ import static com.amazonaws.encryptionsdk.internal.RandomBytesGenerator.generate; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; @ExtendWith(MockitoExtension.class) class EncryptionMaterialsTest { @@ -44,7 +49,7 @@ class EncryptionMaterialsTest { private static final KeyringTraceEntry KEYRING_TRACE_ENTRY = new KeyringTraceEntry("Namespace", "Name", KeyringTraceFlag.ENCRYPTED_DATA_KEY); private static final SecretKey PLAINTEXT_DATA_KEY = new SecretKeySpec(generate(ALGORITHM_SUITE.getDataKeyLength()), ALGORITHM_SUITE.getDataKeyAlgo()); @Mock - private static EncryptedDataKey ENCRYPTED_DATA_KEY; + private static KeyBlob ENCRYPTED_DATA_KEY; private static PrivateKey SIGNING_KEY; @BeforeAll @@ -56,72 +61,50 @@ static void setup() throws Exception { SIGNING_KEY = keyPair.getPrivate(); } - @Test - void testBuilderNullCryptoAlgorithm() { - assertThrows(NullPointerException.class, () -> EncryptionMaterials.newBuilder(null).build()); - } - @Test void testBuilder() { - EncryptionMaterials result = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(KEYRING_TRACE) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .encryptedDataKeys(Collections.singletonList(ENCRYPTED_DATA_KEY)) - .signingKey(SIGNING_KEY) + EncryptionMaterials result = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(KEYRING_TRACE) + .setCleartextDataKey(PLAINTEXT_DATA_KEY) + .setEncryptedDataKeys(Collections.singletonList(ENCRYPTED_DATA_KEY)) + .setTrailingSignatureKey(SIGNING_KEY) .build(); - assertEquals(ALGORITHM_SUITE, result.getAlgorithmSuite()); + assertEquals(ALGORITHM_SUITE, result.getAlgorithm()); assertEquals(ENCRYPTION_CONTEXT, result.getEncryptionContext()); assertEquals(KEYRING_TRACE, result.getKeyringTrace()); - assertEquals(PLAINTEXT_DATA_KEY, result.getPlaintextDataKey()); + assertEquals(PLAINTEXT_DATA_KEY, result.getCleartextDataKey()); assertEquals(1, result.getEncryptedDataKeys().size()); assertEquals(ENCRYPTED_DATA_KEY, result.getEncryptedDataKeys().get(0)); - assertEquals(SIGNING_KEY, result.getSigningKey()); + assertEquals(SIGNING_KEY, result.getTrailingSignatureKey()); } @Test void testInvalidPlaintextDataKey() { SecretKey wrongLength = new SecretKeySpec(generate(ALGORITHM_SUITE.getDataKeyLength() + 1), ALGORITHM_SUITE.getDataKeyAlgo()); - assertThrows(IllegalArgumentException.class, () -> EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .plaintextDataKey(wrongLength) - .signingKey(SIGNING_KEY) - .build()); - SecretKey wrongAlgorithm = new SecretKeySpec(generate(ALGORITHM_SUITE.getDataKeyLength()), "InvalidAlgorithm"); - assertThrows(IllegalArgumentException.class, () -> EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .plaintextDataKey(wrongAlgorithm) - .signingKey(SIGNING_KEY) - .build()); - EncryptionMaterials materials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .signingKey(SIGNING_KEY) + EncryptionMaterials materials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setTrailingSignatureKey(SIGNING_KEY) .build(); assertThrows(IllegalArgumentException.class, () -> materials - .setPlaintextDataKey(wrongAlgorithm, KEYRING_TRACE_ENTRY)); + .setCleartextDataKey(wrongAlgorithm, KEYRING_TRACE_ENTRY)); assertThrows(IllegalArgumentException.class, () -> materials - .setPlaintextDataKey(wrongLength, KEYRING_TRACE_ENTRY)); - } - - @Test - void testInvalidSigningKey() { - assertThrows(IllegalArgumentException.class, () -> EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .signingKey(null) - .build()); - assertThrows(IllegalArgumentException.class, () -> EncryptionMaterials.newBuilder(CryptoAlgorithm.ALG_AES_128_GCM_IV12_TAG16_HKDF_SHA256) - .signingKey(SIGNING_KEY) - .build()); - + .setCleartextDataKey(wrongLength, KEYRING_TRACE_ENTRY)); } @Test void testToBuilder() { - EncryptionMaterials expected = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .encryptionContext(ENCRYPTION_CONTEXT) - .keyringTrace(KEYRING_TRACE) - .plaintextDataKey(PLAINTEXT_DATA_KEY) - .encryptedDataKeys(Collections.singletonList(ENCRYPTED_DATA_KEY)) - .signingKey(SIGNING_KEY) + EncryptionMaterials expected = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setEncryptionContext(ENCRYPTION_CONTEXT) + .setKeyringTrace(KEYRING_TRACE) + .setCleartextDataKey(PLAINTEXT_DATA_KEY) + .setEncryptedDataKeys(Collections.singletonList(ENCRYPTED_DATA_KEY)) + .setTrailingSignatureKey(SIGNING_KEY) .build(); EncryptionMaterials actual = expected.toBuilder().build(); @@ -132,8 +115,9 @@ void testToBuilder() { @Test void testAddEncryptedDataKey() { - EncryptionMaterials materials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .signingKey(SIGNING_KEY) + EncryptionMaterials materials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setTrailingSignatureKey(SIGNING_KEY) .build(); assertThrows(NullPointerException.class, () -> materials.addEncryptedDataKey(null, KEYRING_TRACE_ENTRY)); @@ -148,28 +132,34 @@ void testAddEncryptedDataKey() { @Test void testSetPlaintextDataKey() { - EncryptionMaterials materials = EncryptionMaterials.newBuilder(ALGORITHM_SUITE) - .signingKey(SIGNING_KEY) + EncryptionMaterials materials = EncryptionMaterials.newBuilder() + .setAlgorithm(ALGORITHM_SUITE) + .setTrailingSignatureKey(SIGNING_KEY) .build(); - assertThrows(NullPointerException.class, () -> materials.setPlaintextDataKey(null, KEYRING_TRACE_ENTRY)); - assertThrows(NullPointerException.class, () -> materials.setPlaintextDataKey(PLAINTEXT_DATA_KEY, null)); + assertThrows(NullPointerException.class, () -> materials.setCleartextDataKey(null, KEYRING_TRACE_ENTRY)); + assertThrows(NullPointerException.class, () -> materials.setCleartextDataKey(PLAINTEXT_DATA_KEY, null)); - materials.setPlaintextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY); - assertEquals(PLAINTEXT_DATA_KEY, materials.getPlaintextDataKey()); + materials.setCleartextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY); + assertEquals(PLAINTEXT_DATA_KEY, materials.getCleartextDataKey()); assertEquals(1, materials.getKeyringTrace().getEntries().size()); assertEquals(KEYRING_TRACE_ENTRY, materials.getKeyringTrace().getEntries().get(0)); - assertThrows(IllegalStateException.class, () -> materials.setPlaintextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY)); + assertThrows(IllegalStateException.class, () -> materials.setCleartextDataKey(PLAINTEXT_DATA_KEY, KEYRING_TRACE_ENTRY)); } @Test void testGetOptionalProperties() { - EncryptionMaterials materials = EncryptionMaterials.newBuilder(CryptoAlgorithm.ALG_AES_128_GCM_IV12_TAG16_HKDF_SHA256) - .build(); - - assertThrows(IllegalStateException.class, materials::getPlaintextDataKey); - assertThrows(IllegalStateException.class, materials::getSigningKey); + EncryptionMaterials materials = EncryptionMaterials.newBuilder() + .build(); + + assertNull(materials.getAlgorithm()); + assertNull(materials.getCleartextDataKey()); + assertFalse(materials.hasCleartextDataKey()); + assertTrue(materials.getEncryptedDataKeys().isEmpty()); + assertNull(materials.getTrailingSignatureKey()); + assertTrue(materials.getKeyringTrace().getEntries().isEmpty()); + assertTrue(materials.getEncryptionContext().isEmpty()); } }