com.amazonaws.services.dynamodbv2.datamodeling.encryption.providers.KeyStoreMaterialsProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aws-dynamodb-encryption-java Show documentation
Show all versions of aws-dynamodb-encryption-java Show documentation
AWS DynamoDB Encryption Client for AWS Java SDK v1
/*
* Copyright 2014 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.services.dynamodbv2.datamodeling.encryption.providers;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStore.Entry;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore.ProtectionParameter;
import java.security.KeyStore.SecretKeyEntry;
import java.security.KeyStore.TrustedCertificateEntry;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableEntryException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException;
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.EncryptionContext;
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.materials.AsymmetricRawMaterials;
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.materials.DecryptionMaterials;
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.materials.EncryptionMaterials;
import com.amazonaws.services.dynamodbv2.datamodeling.encryption.materials.SymmetricRawMaterials;
/**
* @author Greg Rubin
*/
public class KeyStoreMaterialsProvider implements EncryptionMaterialsProvider {
private final Map description;
private final String encryptionAlias;
private final String signingAlias;
private final ProtectionParameter encryptionProtection;
private final ProtectionParameter signingProtection;
private final KeyStore keyStore;
private final AtomicReference currMaterials =
new AtomicReference();
public KeyStoreMaterialsProvider(KeyStore keyStore, String encryptionAlias, String signingAlias, Map description)
throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
this(keyStore, encryptionAlias, signingAlias, null, null, description);
}
public KeyStoreMaterialsProvider(KeyStore keyStore, String encryptionAlias, String signingAlias,
ProtectionParameter encryptionProtection, ProtectionParameter signingProtection,
Map description)
throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
super();
this.keyStore = keyStore;
this.encryptionAlias = encryptionAlias;
this.signingAlias = signingAlias;
this.encryptionProtection = encryptionProtection;
this.signingProtection = signingProtection;
this.description = Collections.unmodifiableMap(new HashMap(description));
validateKeys();
loadKeys();
}
@Override
public DecryptionMaterials getDecryptionMaterials(EncryptionContext context) {
CurrentMaterials materials = currMaterials.get();
if (context.getMaterialDescription().entrySet().containsAll(description.entrySet())) {
if (materials.encryptionEntry instanceof SecretKeyEntry) {
return materials.symRawMaterials;
} else {
try {
return makeAsymMaterials(materials, context.getMaterialDescription());
} catch (GeneralSecurityException ex) {
throw new DynamoDBMappingException("Unable to decrypt envelope key", ex);
}
}
} else {
return null;
}
}
@Override
public EncryptionMaterials getEncryptionMaterials(EncryptionContext context) {
CurrentMaterials materials = currMaterials.get();
if (materials.encryptionEntry instanceof SecretKeyEntry) {
return materials.symRawMaterials;
} else {
try {
return makeAsymMaterials(materials, description);
} catch (GeneralSecurityException ex) {
throw new DynamoDBMappingException("Unable to encrypt envelope key", ex);
}
}
}
private AsymmetricRawMaterials makeAsymMaterials(CurrentMaterials materials,
Map description) throws GeneralSecurityException {
KeyPair encryptionPair = entry2Pair(materials.encryptionEntry);
if (materials.signingEntry instanceof SecretKeyEntry) {
return new AsymmetricRawMaterials(encryptionPair,
((SecretKeyEntry) materials.signingEntry).getSecretKey(), description);
} else {
return new AsymmetricRawMaterials(encryptionPair, entry2Pair(materials.signingEntry),
description);
}
}
private static KeyPair entry2Pair(Entry entry) {
PublicKey pub = null;
PrivateKey priv = null;
if (entry instanceof PrivateKeyEntry) {
PrivateKeyEntry pk = (PrivateKeyEntry) entry;
if (pk.getCertificate() != null) {
pub = pk.getCertificate().getPublicKey();
}
priv = pk.getPrivateKey();
} else if (entry instanceof TrustedCertificateEntry) {
TrustedCertificateEntry tc = (TrustedCertificateEntry) entry;
pub = tc.getTrustedCertificate().getPublicKey();
} else {
throw new IllegalArgumentException(
"Only entry types PrivateKeyEntry and TrustedCertificateEntry are supported.");
}
return new KeyPair(pub, priv);
}
/**
* Reloads the keys from the underlying keystore by calling
* {@link KeyStore#getEntry(String, ProtectionParameter)} again for each of them.
*/
@Override
public void refresh() {
try {
loadKeys();
} catch (GeneralSecurityException ex) {
throw new DynamoDBMappingException("Unable to load keys from keystore", ex);
}
}
private void validateKeys() throws KeyStoreException {
if (!keyStore.containsAlias(encryptionAlias)) {
throw new IllegalArgumentException("Keystore does not contain alias: "
+ encryptionAlias);
}
if (!keyStore.containsAlias(signingAlias)) {
throw new IllegalArgumentException("Keystore does not contain alias: "
+ signingAlias);
}
}
private void loadKeys() throws NoSuchAlgorithmException, UnrecoverableEntryException,
KeyStoreException {
Entry encryptionEntry = keyStore.getEntry(encryptionAlias, encryptionProtection);
Entry signingEntry = keyStore.getEntry(signingAlias, signingProtection);
CurrentMaterials newMaterials = new CurrentMaterials(encryptionEntry, signingEntry);
currMaterials.set(newMaterials);
}
private class CurrentMaterials {
public final Entry encryptionEntry;
public final Entry signingEntry;
public final SymmetricRawMaterials symRawMaterials;
public CurrentMaterials(Entry encryptionEntry, Entry signingEntry) {
super();
this.encryptionEntry = encryptionEntry;
this.signingEntry = signingEntry;
if (encryptionEntry instanceof SecretKeyEntry) {
if (signingEntry instanceof SecretKeyEntry) {
this.symRawMaterials = new SymmetricRawMaterials(
((SecretKeyEntry) encryptionEntry).getSecretKey(),
((SecretKeyEntry) signingEntry).getSecretKey(),
description);
} else {
this.symRawMaterials = new SymmetricRawMaterials(
((SecretKeyEntry) encryptionEntry).getSecretKey(),
entry2Pair(signingEntry),
description);
}
} else {
this.symRawMaterials = null;
}
}
}
}