All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.encryptionsdk.DefaultCryptoMaterialsManager Maven / Gradle / Ivy

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.amazonaws.encryptionsdk;

import static com.amazonaws.encryptionsdk.internal.Utils.assertNonNull;

import com.amazonaws.encryptionsdk.exception.AwsCryptoException;
import com.amazonaws.encryptionsdk.exception.CannotUnwrapDataKeyException;
import com.amazonaws.encryptionsdk.internal.Constants;
import com.amazonaws.encryptionsdk.internal.TrailingSignatureAlgorithm;
import com.amazonaws.encryptionsdk.internal.Utils;
import com.amazonaws.encryptionsdk.model.DecryptionMaterials;
import com.amazonaws.encryptionsdk.model.DecryptionMaterialsRequest;
import com.amazonaws.encryptionsdk.model.EncryptionMaterials;
import com.amazonaws.encryptionsdk.model.EncryptionMaterialsRequest;
import com.amazonaws.encryptionsdk.model.KeyBlob;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The default implementation of {@link CryptoMaterialsManager}, used implicitly when passing a
 * {@link MasterKeyProvider} to methods in {@link AwsCrypto}.
 *
 * 

This default implementation delegates to a specific {@link MasterKeyProvider} specified at * construction time. It also handles generating trailing signature keys when needed, placing them * in the encryption context (and extracting them at decrypt time). */ public class DefaultCryptoMaterialsManager implements CryptoMaterialsManager { private final MasterKeyProvider mkp; private final CryptoAlgorithm DEFAULT_CRYPTO_ALGORITHM = CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA384_ECDSA_P384; /** @param mkp The master key provider to delegate to */ public DefaultCryptoMaterialsManager(MasterKeyProvider mkp) { Utils.assertNonNull(mkp, "mkp"); this.mkp = mkp; } @Override public EncryptionMaterials getMaterialsForEncrypt(EncryptionMaterialsRequest request) { Map context = request.getContext(); CryptoAlgorithm algo = request.getRequestedAlgorithm(); if (algo == null) { algo = DEFAULT_CRYPTO_ALGORITHM; } KeyPair trailingKeys = null; if (algo.getTrailingSignatureLength() > 0) { try { trailingKeys = generateTrailingSigKeyPair(algo); if (context.containsKey(Constants.EC_PUBLIC_KEY_FIELD)) { throw new IllegalArgumentException( "EncryptionContext contains reserved field " + Constants.EC_PUBLIC_KEY_FIELD); } // make mutable context = new HashMap<>(context); context.put(Constants.EC_PUBLIC_KEY_FIELD, serializeTrailingKeyForEc(algo, trailingKeys)); } catch (final GeneralSecurityException ex) { throw new AwsCryptoException(ex); } } final MasterKeyRequest.Builder mkRequestBuilder = MasterKeyRequest.newBuilder(); mkRequestBuilder.setEncryptionContext(context); mkRequestBuilder.setStreaming(request.getPlaintextSize() == -1); if (request.getPlaintext() != null) { mkRequestBuilder.setPlaintext(request.getPlaintext()); } else { mkRequestBuilder.setSize(request.getPlaintextSize()); } @SuppressWarnings("unchecked") final List mks = (List) assertNonNull(mkp, "provider").getMasterKeysForEncryption(mkRequestBuilder.build()); if (mks.isEmpty()) { throw new IllegalArgumentException("No master keys provided"); } DataKey dataKey = mks.get(0).generateDataKey(algo, context); List keyBlobs = new ArrayList<>(mks.size()); keyBlobs.add(new KeyBlob(dataKey)); for (int i = 1; i < mks.size(); i++) { //noinspection unchecked keyBlobs.add(new KeyBlob(mks.get(i).encryptDataKey(algo, context, dataKey))); } //noinspection unchecked return EncryptionMaterials.newBuilder() .setAlgorithm(algo) .setCleartextDataKey(dataKey.getKey()) .setEncryptedDataKeys(keyBlobs) .setEncryptionContext(context) .setTrailingSignatureKey(trailingKeys == null ? null : trailingKeys.getPrivate()) .setMasterKeys(mks) .build(); } @Override public DecryptionMaterials decryptMaterials(DecryptionMaterialsRequest request) { DataKey dataKey = mkp.decryptDataKey( request.getAlgorithm(), request.getEncryptedDataKeys(), request.getEncryptionContext()); if (dataKey == null) { throw new CannotUnwrapDataKeyException("Could not decrypt any data keys"); } PublicKey pubKey = null; if (request.getAlgorithm().getTrailingSignatureLength() > 0) { try { String serializedPubKey = request.getEncryptionContext().get(Constants.EC_PUBLIC_KEY_FIELD); if (serializedPubKey == null) { throw new AwsCryptoException("Missing trailing signature public key"); } pubKey = deserializeTrailingKeyFromEc(request.getAlgorithm(), serializedPubKey); } catch (final IllegalStateException ex) { throw new AwsCryptoException(ex); } } else if (request.getEncryptionContext().containsKey(Constants.EC_PUBLIC_KEY_FIELD)) { throw new AwsCryptoException("Trailing signature public key found for non-signed algorithm"); } return DecryptionMaterials.newBuilder() .setDataKey(dataKey) .setTrailingSignatureKey(pubKey) .build(); } private PublicKey deserializeTrailingKeyFromEc(CryptoAlgorithm algo, String pubKey) { return TrailingSignatureAlgorithm.forCryptoAlgorithm(algo).deserializePublicKey(pubKey); } private static String serializeTrailingKeyForEc(CryptoAlgorithm algo, KeyPair trailingKeys) { return TrailingSignatureAlgorithm.forCryptoAlgorithm(algo) .serializePublicKey(trailingKeys.getPublic()); } private static KeyPair generateTrailingSigKeyPair(CryptoAlgorithm algo) throws GeneralSecurityException { return TrailingSignatureAlgorithm.forCryptoAlgorithm(algo).generateKey(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy