Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a basic example for encrypting and decrypting with a KMS CMK #135

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* 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.crypto.examples;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CryptoResult;
import com.amazonaws.encryptionsdk.kms.KmsMasterKey;
import com.amazonaws.encryptionsdk.kms.KmsMasterKeyProvider;

/**
* <p>
* Encrypts and then decrypts data using an AWS KMS customer master key.
*
* <p>
* Arguments:
* <ol>
* <li>Key ARN: For help finding the Amazon Resource Name (ARN) of your KMS customer master
* key (CMK), see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html
* </ol>
*/
public class BasicEncryptionExample {

private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8);

public static void main(final String[] args) {
final String keyArn = args[0];

encryptAndDecrypt(keyArn);
}

static void encryptAndDecrypt(final String keyArn) {
// 1. Instantiate the SDK
final AwsCrypto crypto = new AwsCrypto();

// 2. Instantiate a KMS master key provider
final KmsMasterKeyProvider prov = KmsMasterKeyProvider.builder().withKeysForEncryption(keyArn).build();

// 3. Create an encryption context
//
// Most encrypted data should have an associated encryption context
// to protect integrity. This sample uses placeholder values.
//
// For more information see:
// blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
final Map<String, String> context = Collections.singletonMap("ExampleContextKey", "ExampleContextValue");

// 4. Encrypt the data
final CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData(prov, EXAMPLE_DATA, context);
final byte[] ciphertext = encryptResult.getResult();

// 5. Decrypt the data
final CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(prov, ciphertext);

// 6. Before verifying the plaintext, verify that the customer master key that
// was used in the encryption operation was the one supplied to the master key provider.
if (!decryptResult.getMasterKeyIds().get(0).equals(keyArn)) {
throw new IllegalStateException("Wrong key ID!");
}

// 7. Also, verify that the encryption context in the result contains the
// encryption context supplied to the encryptData method. Because the
// SDK can add values to the encryption context, don't require that
// the entire context matches.
if (!context.entrySet().stream()
.allMatch(e -> e.getValue().equals(decryptResult.getEncryptionContext().get(e.getKey())))) {
throw new IllegalStateException("Wrong Encryption Context!");
}

// 8. Verify that the decrypted plaintext matches the original plaintext
assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

/**
* A keyring trace containing all of the actions that keyrings have taken on a set of encryption materials.
*/
public class KeyringTrace {

private final List<KeyringTraceEntry> entries = new ArrayList<>();

/**
* Add a new entry to the keyring trace.
*
* @param keyNamespace The namespace for the key.
* @param keyName The name of the key.
* @param flags A set of one or more KeyringTraceFlag enums
* indicating what actions were taken by a keyring.
*/
public void add(String keyNamespace, String keyName, KeyringTraceFlag... flags) {
entries.add(new KeyringTraceEntry(keyNamespace, keyName,
new HashSet<>(Arrays.asList(flags))));
}

/**
* Gets an unmodifiable list of `KeyringTraceEntry`s ordered sequentially
* according to the order the actions were taken, with the earliest action
* corresponding to the first `KeyringTraceEntry` in the list.
*
* @return An unmodifiable list of `KeyringTraceEntry`s
*/
public List<KeyringTraceEntry> getEntries() {
return Collections.unmodifiableList(entries);
}

@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("entries", entries)
.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* 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 org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.util.Collections;
import java.util.Objects;
import java.util.Set;

import static org.apache.commons.lang3.Validate.notBlank;
import static org.apache.commons.lang3.Validate.notEmpty;

/**
* A representation of an action that a keyring has taken on a data key.
*/
public class KeyringTraceEntry {

private final String keyNamespace;
private final String keyName;
private final Set<KeyringTraceFlag> flags;

/**
* Constructs a new `KeyringTraceEntry`.
*
* @param keyNamespace The namespace for the key.
* @param keyName The name of the key.
* @param flags A set of one or more KeyringTraceFlag enums
* indicating what actions were taken by a keyring.
*/
KeyringTraceEntry(final String keyNamespace, final String keyName, final Set<KeyringTraceFlag> flags) {
notBlank(keyNamespace, "keyNamespace is required");
notBlank(keyName, "keyName is required");
notEmpty(flags, "At least one flag is required");

this.keyNamespace = keyNamespace;
this.keyName = keyName;
this.flags = Collections.unmodifiableSet(flags);
}

/**
* Returns the key namespace.
*
* @return The key namespace.
*/
public String getKeyNamespace() {
return this.keyNamespace;
}

/**
* Returns the key name.
*
* @return THe key name.
*/
public String getKeyName() {
return this.keyName;
}

/**
* Returns an unmodifiable set of flags that indicate
* which actions were taken by a keyring.
*
* @return The unmodifiable set of flags.
*/
public Set<KeyringTraceFlag> getFlags() {
return this.flags;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
KeyringTraceEntry that = (KeyringTraceEntry) o;
return Objects.equals(keyNamespace, that.keyNamespace) &&
Objects.equals(keyName, that.keyName) &&
Objects.equals(flags, that.flags);
}

@Override
public int hashCode() {
return Objects.hash(keyNamespace, keyName, flags);
}

@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
.append("keyNamespace", this.keyNamespace)
.append("keyName", this.keyName)
.append("flags", this.flags)
.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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;

/**
* Enum representing the possible actions a keyring may take on the
* different wrapping keys it manages.
*/
public enum KeyringTraceFlag {

/**
* A flag to represent that a keyring has generated a plaintext data key.
*/
WRAPPING_KEY_GENERATED_DATA_KEY,

/**
* A flag to represent that a keyring has created an encrypted data key.
*/
WRAPPING_KEY_ENCRYPTED_DATA_KEY,

/**
* A flag to represent that a keyring has obtained the
* corresponding plaintext data key from an encrypted data key.
*/
WRAPPING_KEY_DECRYPTED_DATA_KEY,

/**
* A flag to represent that the keyring has cryptographically
* bound the encryption context to a newly created encrypted data key.
*/
WRAPPING_KEY_SIGNED_ENC_CTX,

/**
* A flag to represent that the keyring has verified that an encrypted
* data key was originally created with a particular encryption context.
*/
WRAPPING_KEY_VERIFIED_ENC_CTX
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
import java.security.PublicKey;

import com.amazonaws.encryptionsdk.DataKey;
import com.amazonaws.encryptionsdk.keyrings.KeyringTrace;

public final class DecryptionMaterials {
private final DataKey<?> dataKey;
private final PublicKey trailingSignatureKey;
private final KeyringTrace keyringTrace;

private DecryptionMaterials(Builder b) {
dataKey = b.getDataKey();
trailingSignatureKey = b.getTrailingSignatureKey();
keyringTrace = b.getKeyringTrace();
}

public DataKey<?> getDataKey() {
Expand All @@ -21,6 +24,10 @@ public PublicKey getTrailingSignatureKey() {
return trailingSignatureKey;
}

public KeyringTrace getKeyringTrace() {
return keyringTrace;
}

public static Builder newBuilder() {
return new Builder();
}
Expand All @@ -32,10 +39,12 @@ public Builder toBuilder() {
public static final class Builder {
private DataKey<?> dataKey;
private PublicKey trailingSignatureKey;
private KeyringTrace keyringTrace;

private Builder(DecryptionMaterials result) {
this.dataKey = result.getDataKey();
this.trailingSignatureKey = result.getTrailingSignatureKey();
this.keyringTrace = result.getKeyringTrace();
}

private Builder() {}
Expand All @@ -58,6 +67,15 @@ public Builder setTrailingSignatureKey(PublicKey trailingSignatureKey) {
return this;
}

public KeyringTrace getKeyringTrace() {
return keyringTrace;
}

public Builder setKeyringTrace(KeyringTrace keyringTrace) {
this.keyringTrace = keyringTrace;
return this;
}

public DecryptionMaterials build() {
return new DecryptionMaterials(this);
}
Expand Down
Loading