Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2013-2015 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.s3.internal.crypto;
 
 import static com.amazonaws.services.s3.AmazonS3EncryptionClient.USER_AGENT;
 import static com.amazonaws.services.s3.model.CryptoStorageMode.InstructionFile;
 import static com.amazonaws.services.s3.model.CryptoStorageMode.ObjectMetadata;
 import static com.amazonaws.services.s3.model.InstructionFileId.DEFAULT_INSTRUCTION_FILE_SUFFIX;
 import static com.amazonaws.services.s3.model.InstructionFileId.DOT;
 import static com.amazonaws.services.s3.model.S3DataSource.Utils.cleanupDataSource;
 import static com.amazonaws.util.BinaryUtils.copyAllBytesFrom;
 import static com.amazonaws.util.IOUtils.closeQuietly;
 import static com.amazonaws.util.LengthCheckInputStream.EXCLUDE_SKIPPED_BYTES;
 import static com.amazonaws.util.StringUtils.UTF8;
 import static com.amazonaws.util.Throwables.failure;
 
 import java.io.File;
 import java.util.Map;
 
 
 
Common implementation for different S3 cryptographic modules.
 
 public abstract class S3CryptoModuleBase<T extends MultipartUploadCryptoContext>
         extends S3CryptoModule<T> {
     private static final boolean IS_MULTI_PART = true;
     protected static final int DEFAULT_BUFFER_SIZE = 1024*2;    // 2K
     protected final Log log = LogFactory.getLog(getClass());
    protected final S3CryptoScheme cryptoScheme;
    protected final ContentCryptoScheme contentCryptoScheme;
    
A read-only copy of the crypto configuration.
    protected final CryptoConfiguration cryptoConfig;

    
Map of data about in progress encrypted multipart uploads.
    protected final  Map<String, T> multipartUploadContexts =
        Collections.synchronizedMap(new HashMap<String,T>());
    protected final S3Direct s3;
    protected final AWSKMSClient kms;

    

Parameters:
cryptoConfig a read-only copy of the crypto configuration.
    protected S3CryptoModuleBase(AWSKMSClient kmsS3Direct s3,
            AWSCredentialsProvider credentialsProvider,
            EncryptionMaterialsProvider kekMaterialsProvider,
            CryptoConfiguration cryptoConfig) {
        if (!cryptoConfig.isReadOnly())
            throw new IllegalArgumentException("The cryto configuration parameter is required to be read-only");
        this. = kekMaterialsProvider;
        this. = s3;
        this. = cryptoConfig;
        this. = S3CryptoScheme.from(cryptoConfig.getCryptoMode());
        this. = kms;
    }

    
For testing purposes only.
    protected S3CryptoModuleBase(S3Direct s3,
            AWSCredentialsProvider credentialsProvider,
            EncryptionMaterialsProvider kekMaterialsProvider,
            CryptoConfiguration cryptoConfig) {
        this. = kekMaterialsProvider;
        this. = s3;
        this. = cryptoConfig;
        this. = S3CryptoScheme.from(cryptoConfig.getCryptoMode());
        this. = null;
    }

    
Returns the length of the ciphertext computed from the length of the plaintext.

Parameters:
plaintextLength a non-negative number
Returns:
a non-negative number
    protected abstract long ciphertextLength(long plaintextLength);
    //////////////////////// Common Implementation ////////////////////////
    @Override
        // TODO: consider cloning req before proceeding further to reduce side
        // effects
        appendUserAgent(req);
        return .getStorageMode() == 
             ? putObjectUsingInstructionFile(req)
             : putObjectUsingMetadata(req);
    }
        ContentCryptoMaterial cekMaterial = createContentCryptoMaterial(req);
        // Wraps the object data with a cipher input stream
        final File fileOrig = req.getFile();
        final InputStream isOrig = req.getInputStream();
        PutObjectRequest wrappedReq = wrapWithCipher(reqcekMaterial);
        // Update the metadata
                req.getMetadata(), req.getFile(), cekMaterial));
        // Put the encrypted object into S3
        try {
            return .putObject(wrappedReq);
        } finally {
            cleanupDataSource(reqfileOrigisOrigwrappedReq.getInputStream(), );
        }
    }

    
Puts an encrypted object into S3, and puts an instruction file into S3. Encryption info is stored in the instruction file.

Parameters:
putObjectRequest The request object containing all the parameters to upload a new object to Amazon S3.
Returns:
A com.amazonaws.services.s3.model.PutObjectResult object containing the information returned by Amazon S3 for the new, created object.
            PutObjectRequest putObjectRequest) {
        final File fileOrig = putObjectRequest.getFile();
        final InputStream isOrig = putObjectRequest.getInputStream();
        final PutObjectRequest putInstFileRequest = putObjectRequest.clone()
            .withFile(null)
            .withInputStream(null)
            ;
        putInstFileRequest.setKey(putInstFileRequest.getKey() + 
                + );
        // Create instruction
        ContentCryptoMaterial cekMaterial = createContentCryptoMaterial(putObjectRequest);
        // Wraps the object data with a cipher input stream; note the metadata
        // is mutated as a side effect.
        PutObjectRequest req = wrapWithCipher(putObjectRequestcekMaterial);
        // Put the encrypted object into S3
        final PutObjectResult result;
        try {
            result = .putObject(req);
        } finally {
            cleanupDataSource(putObjectRequestfileOrigisOrig,
                    req.getInputStream(), );
        }
        // Put the instruction file into S3
        .putObject(updateInstructionPutRequest(putInstFileRequest,
                cekMaterial));
        // Return the result of the encrypted object PUT.
        return result;
    }
    @Override
    public final void abortMultipartUploadSecurely(AbortMultipartUploadRequest req) {
        .abortMultipartUpload(req);
    }
    @Override
    public final CopyPartResult copyPartSecurely(CopyPartRequest copyPartRequest) {
        String uploadId = copyPartRequest.getUploadId();
        T uploadContext = .get(uploadId);
        CopyPartResult result = .copyPart(copyPartRequest);
        if (uploadContext != null && !uploadContext.hasFinalPartBeenSeen())
            uploadContext.setHasFinalPartBeenSeen(true);
        return result;
    }
            ContentCryptoMaterial cekMaterial);
    @Override
            InitiateMultipartUploadRequest req) {
        appendUserAgent(req);
        // Generate a one-time use symmetric key and initialize a cipher to
        // encrypt object data
        ContentCryptoMaterial cekMaterial = createContentCryptoMaterial(req);
        if (.getStorageMode() == ) {
            ObjectMetadata metadata = req.getObjectMetadata();
            if (metadata == null)
                metadata = new ObjectMetadata();
            // Store encryption info in metadata
                    metadatanullcekMaterial));
        }
        T uploadContext = newUploadContext(reqcekMaterial);
        if (req instanceof MaterialsDescriptionProvider) {
            MaterialsDescriptionProvider p = (MaterialsDescriptionProviderreq;
            uploadContext.setMaterialsDescription(p.getMaterialsDescription());
        }
        .put(result.getUploadId(), uploadContext);
        return result;
    }
    //// specific crypto module behavior for uploading parts.
    abstract CipherLite cipherLiteForNextPart(T uploadContext);
    abstract long computeLastPartSize(UploadPartRequest req);
            I islong partSize);
    abstract void updateUploadContext(T uploadContextSdkFilterInputStream is);
    

NOTE: Because the encryption process requires context from previous blocks, parts uploaded with the AmazonS3EncryptionClient (as opposed to the normal AmazonS3Client) must be uploaded serially, and in order. Otherwise, the previous encryption context isn't available to use when encrypting the current part.

    @Override
        appendUserAgent(req);
        final int blockSize = .getBlockSizeInBytes();
        final boolean isLastPart = req.isLastPart();
        final String uploadId = req.getUploadId();
        final long partSize = req.getPartSize();
        final boolean partSizeMultipleOfCipherBlockSize = 0 == (partSize % blockSize);
        if (!isLastPart && !partSizeMultipleOfCipherBlockSize) {
            throw new AmazonClientException(
                "Invalid part size: part sizes for encrypted multipart uploads must be multiples "
                    + "of the cipher block size ("
                    + blockSize
                    + ") with the exception of the last part.");
        }
        final T uploadContext = .get(uploadId);
        if (uploadContext == null) {
            throw new AmazonClientException(
                "No client-side information available on upload ID " + uploadId);
        }
        final UploadPartResult result;
        // Checks the parts are uploaded in series
        uploadContext.beginPartUpload(req.getPartNumber());
        CipherLite cipherLite = cipherLiteForNextPart(uploadContext);
        final File fileOrig = req.getFile();
        final InputStream isOrig = req.getInputStream();
        SdkFilterInputStream isCurr = null;
        try {
            CipherLiteInputStream clis = newMultipartS3CipherInputStream(reqcipherLite);
            isCurr = clis// so the clis will be closed (in the finally block below) upon
                       // unexpected failure should we opened a file undereath
            isCurr = wrapForMultipart(clispartSize);
            req.setInputStream(isCurr);
            // Treat all encryption requests as input stream upload requests,
            // not as file upload requests.
            req.setFile(null);
            req.setFileOffset(0);
            // The last part of the multipart upload will contain an extra
            // 16-byte mac
            if (isLastPart) {
                // We only change the size of the last part
                long lastPartSize = computeLastPartSize(req);
                if (lastPartSize > -1)
                    req.setPartSize(lastPartSize);
                if (uploadContext.hasFinalPartBeenSeen()) {
                    throw new AmazonClientException(
                        "This part was specified as the last part in a multipart upload, but a previous part was already marked as the last part.  "
                      + "Only the last part of the upload should be marked as the last part.");
                }
            }
            result = .uploadPart(req);
        } finally {
            cleanupDataSource(reqfileOrigisOrigisCurr);
            uploadContext.endPartUpload();
        }
        if (isLastPart)
            uploadContext.setHasFinalPartBeenSeen(true);
        updateUploadContext(uploadContextisCurr);
        return result;
    }
            UploadPartRequest reqCipherLite cipherLite) {
        final File fileOrig = req.getFile();
        final InputStream isOrig = req.getInputStream();
        InputStream isCurr = null;
        try {
            if (fileOrig == null) {
                if (isOrig == null) {
                    throw new IllegalArgumentException(
                        "A File or InputStream must be specified when uploading part");
                }
                isCurr = isOrig;
            } else {
                isCurr = new ResettableInputStream(fileOrig);
            }
            isCurr = new InputSubstream(isCurr,
                    req.getFileOffset(),
                    req.getPartSize(),
                    req.isLastPart());
            return cipherLite.markSupported()
                 ? new CipherLiteInputStream(isCurrcipherLite,
                       ,
                       req.isLastPart())
                 : new RenewableCipherLiteInputStream(isCurrcipherLite,
                        ,
                        req.isLastPart());
        } catch (Exception e) {
            cleanupDataSource(reqfileOrigisOrigisCurr);
            throw failure(e,"Unable to create cipher input stream");
        }
    }
    @Override
            CompleteMultipartUploadRequest req) {
        appendUserAgent(req);
        String uploadId = req.getUploadId();
        final T uploadContext = .get(uploadId);
        if (uploadContext != null && !uploadContext.hasFinalPartBeenSeen()) {
            throw new AmazonClientException(
                "Unable to complete an encrypted multipart upload without being told which part was the last.  "
                + "Without knowing which part was the last, the encrypted data in Amazon S3 is incomplete and corrupt.");
        }
        // In InstructionFile mode, we want to write the instruction file only
        // after the whole upload has completed correctly.
        if (uploadContext != null
        &&  .getStorageMode() == ) {
            // Put the instruction file into S3
                    uploadContext.getBucketName(), uploadContext.getKey(),
                    uploadContext.getContentCryptoMaterial()));
        }
        .remove(uploadId);
        return result;
    }
            ObjectMetadata metadataFile fileContentCryptoMaterial instruction) {
        if (metadata == null)
            metadata = new ObjectMetadata();
        if (file != null) {
            Mimetypes mimetypes = Mimetypes.getInstance();
            metadata.setContentType(mimetypes.getMimetype(file));
        }
        return instruction.toObjectMetadata(metadata.getCryptoMode());
    }

    
Creates and returns a non-null content crypto material for the given request.

Throws:
com.amazonaws.AmazonClientException if no encryption material can be found.
            AmazonWebServiceRequest req) {
        if (req instanceof EncryptionMaterialsFactory) {
            // per request level encryption materials
            EncryptionMaterialsFactory f = (EncryptionMaterialsFactory)req;
            final EncryptionMaterials materials = f.getEncryptionMaterials();
            if (materials != null) {
                return buildContentCryptoMaterial(materials,
                        .getCryptoProvider(), req);
            }
        }
        if (req instanceof MaterialsDescriptionProvider) {
            // per request level material description
            MaterialsDescriptionProvider mdp = (MaterialsDescriptionProviderreq;
            Map<String,Stringmatdesc = mdp.getMaterialsDescription();
                    matdesc,
                    .getCryptoProvider(), req);
            if (ccm != null)
                return ccm;
            if (matdesc != null) {
                throw new AmazonClientException(
                    "No material available from the encryption material provider for description "
                        + matdesc);
            }
            // if there is no material description, fall thru to use
            // the per s3 client level encryption  materials
        }
        // per s3 client level encryption materials
                .getCryptoProvider(), req);
    }

    
Returns the content encryption material generated with the given kek material, material description and security providers; or null if the encryption material cannot be found for the specified description.
            EncryptionMaterialsProvider kekMaterialProvider,
            Map<StringStringmaterialsDescriptionProvider provider,
            AmazonWebServiceRequest req) {
        EncryptionMaterials kekMaterials =
            kekMaterialProvider.getEncryptionMaterials(materialsDescription);
        if (kekMaterials == null) {
            return null;
        }
        return buildContentCryptoMaterial(kekMaterialsproviderreq);
    }

    
Returns a non-null content encryption material generated with the given kek material and security providers.

Throws:
com.amazonaws.AmazonClientException if no encryption material can be found from the given encryption material provider.
            EncryptionMaterialsProvider kekMaterialProvider,
            Provider providerAmazonWebServiceRequest req) {
        EncryptionMaterials kekMaterials = kekMaterialProvider.getEncryptionMaterials();
        if (kekMaterials == null)
            throw new AmazonClientException("No material available from the encryption material provider");
        return buildContentCryptoMaterial(kekMaterialsproviderreq);
    }
    @Override
    public final void putLocalObjectSecurely(final UploadObjectRequest reqIn,
            String uploadIdOutputStream osthrows IOException {
        UploadObjectRequest req = reqIn.clone();
        final File fileOrig = req.getFile();
        final InputStream isOrig = req.getInputStream();
        final T uploadContext = .get(uploadId);
        ContentCryptoMaterial cekMaterial = uploadContext.getContentCryptoMaterial();
        req = wrapWithCipher(reqcekMaterial);
        try {
            IOUtils.copy(req.getInputStream(), os);
            // so it won't crap out with a false negative at the end; (Not
            // really relevant here)
            uploadContext.setHasFinalPartBeenSeen(true);
        } finally {
            cleanupDataSource(reqfileOrigisOrig,
                    req.getInputStream(), );
            IOUtils.closeQuietly(os);
        }
        return;
    }

    

Parameters:
kekMaterials a non-null encryption material
            EncryptionMaterials kekMaterialsProvider provider,
            AmazonWebServiceRequest req) {
        // Randomly generate the IV
        final byte[] iv = new byte[.getIVLengthInBytes()];
        if (kekMaterials.isKMSEnabled()) {
            GenerateDataKeyRequest keyGenReq = new GenerateDataKeyRequest()
                .withEncryptionContext(kekMaterials.getMaterialsDescription())
                .withKeyId(kekMaterials.getCustomerMasterKeyId())
                .withKeySpec(.getKeySpec());
            keyGenReq
                .withGeneralProgressListener(req.getGeneralProgressListener())
                .withRequestMetricCollector(req.getRequestMetricCollector())
                ;
            GenerateDataKeyResult keyGenRes = .generateDataKey(keyGenReq);
            final SecretKey cek =
                new SecretKeySpec(copyAllBytesFrom(keyGenRes.getPlaintext()),
                        .getKeyGeneratorAlgorithm());
            byte[] keyBlob = copyAllBytesFrom(keyGenRes.getCiphertextBlob());
            return ContentCryptoMaterial.wrap(cekiv,
                    kekMaterialsprovider,
                    new KMSSecuredCEK(keyBlob));
        } else {
            // Generate a one-time use symmetric key and initialize a cipher to encrypt object data
            return ContentCryptoMaterial.create(
                    generateCEK(kekMaterialsprovider),
                    ivkekMaterialsproviderreq);
        }
    }

    

Parameters:
kekMaterials non-null encryption materials
    protected final SecretKey generateCEK(
            final EncryptionMaterials kekMaterials,
            final Provider providerIn) {
        final String keygenAlgo = .getKeyGeneratorAlgorithm();
        KeyGenerator generator;
        try {
            generator = providerIn == null
                ? KeyGenerator.getInstance(keygenAlgo)
                : KeyGenerator.getInstance(keygenAlgoproviderIn);
            generator.init(.getKeyLengthInBits(),
                    .getSecureRandom());
            // Set to true iff the key encryption involves the use of BC's public key
            boolean involvesBCPublicKey = false;
            KeyPair keypair = kekMaterials.getKeyPair();
            if (keypair != null) {
                String keyWrapAlgo = .getKeyWrapScheme().getKeyWrapAlgorithm(keypair.getPublic());
                if (keyWrapAlgo == null) {
                    Provider provider = generator.getProvider();
                    String providerName = provider == null ? null : provider.getName();
                    involvesBCPublicKey = ..equals(providerName);
                }
            }
            SecretKey secretKey = generator.generateKey();
            if (!involvesBCPublicKey || secretKey.getEncoded()[0] != 0)
                return secretKey;
            for (int retry = 0; retry < 9; retry++) {
                // Regenerate the random key due to a bug/feature in BC:
                // https://github.com/aws/aws-sdk-android/issues/15
                secretKey = generator.generateKey();
                if (secretKey.getEncoded()[0] != 0)
                    return secretKey;
            }
            // The probability of getting here is 2^80, which is impossible in practice.
            throw new AmazonClientException("Failed to generate secret key");
        } catch (NoSuchAlgorithmException e) {
            throw new AmazonClientException(
                    "Unable to generate envelope symmetric key:"
                            + e.getMessage(), e);
        }
    }

    
Returns the given PutObjectRequest but has the content as input stream wrapped with a cipher, and configured with some meta data and user metadata.
    protected final <R extends AbstractPutObjectRequest> R wrapWithCipher(
            final R requestContentCryptoMaterial cekMaterial) {
        // Create a new metadata object if there is no metadata already.
        ObjectMetadata metadata = request.getMetadata();
        if (metadata == null) {
            metadata = new ObjectMetadata();
        }
        // Record the original Content MD5, if present, for the unencrypted data
        if (metadata.getContentMD5() != null) {
            metadata.addUserMetadata(.,
                    metadata.getContentMD5());
        }
        // Removes the original content MD5 if present from the meta data.
        metadata.setContentMD5(null);
        // Record the original, unencrypted content-length so it can be accessed
        // later
        final long plaintextLength = plaintextLength(requestmetadata);
        if (plaintextLength >= 0) {
            metadata.addUserMetadata(.,
                    Long.toString(plaintextLength));
            // Put the ciphertext length in the metadata
            metadata.setContentLength(ciphertextLength(plaintextLength));
        }
        request.setMetadata(metadata);
            requestcekMaterialplaintextLength));
        // Treat all encryption requests as input stream upload requests, not as
        // file upload requests.
        request.setFile(null);
        return request;
    }
            AbstractPutObjectRequest reqContentCryptoMaterial cekMaterial,
            long plaintextLength) {
        final File fileOrig = req.getFile();
        final InputStream isOrig = req.getInputStream();
        InputStream isCurr = null;
        try {
            if (fileOrig == null) {
                // When input is a FileInputStream, this wrapping enables
                // unlimited mark-and-reset
                isCurr = isOrig == null ? null : ReleasableInputStream.wrap(isOrig);
            } else {
                isCurr = new ResettableInputStream(fileOrig);
            }
            if (plaintextLength > -1) {
                // S3 allows a single PUT to be no more than 5GB, which
                // therefore won't exceed the maximum length that can be
                // encrypted either using any cipher such as CBC or GCM.
                // This ensures the plain-text read from the underlying data
                // stream has the same length as the expected total.
                isCurr = new LengthCheckInputStream(isCurrplaintextLength,
                        );
            }
            final CipherLite cipherLite = cekMaterial.getCipherLite();
            if (cipherLite.markSupported()) {
                return new CipherLiteInputStream(isCurrcipherLite,
                        );
            } else {
                return new RenewableCipherLiteInputStream(isCurrcipherLite,
                        );
            }
        } catch (Exception e) {
            cleanupDataSource(reqfileOrigisOrigisCurr);
            throw failure(e"Unable to create cipher input stream");
        }
    }

    
Returns the plaintext length from the request and metadata; or -1 if unknown.
    protected final long plaintextLength(AbstractPutObjectRequest request,
            ObjectMetadata metadata) {
        if (request.getFile() != null) {
            return request.getFile().length();
        } else if (request.getInputStream() != null
                && metadata.getRawMetadataValue(.) != null) {
            return metadata.getContentLength();
        }
        return -1;
    }
    public final S3CryptoScheme getS3CryptoScheme() {
        return ;
    }

    
Updates put request to store the specified instruction object in S3.

Parameters:
req The put-instruction-file request for the instruction file to be stored in S3.
cekMaterial The instruction object to be stored in S3.
Returns:
A put request to store the specified instruction object in S3.
            PutObjectRequest reqContentCryptoMaterial cekMaterial) {
        byte[] bytes =  cekMaterial.toJsonString(.getCryptoMode())
                                   .getBytes();
        ObjectMetadata metadata = req.getMetadata();
        if (metadata == null) {
            metadata = new ObjectMetadata();
            req.setMetadata(metadata);
        }
        // Set the content-length of the upload
        metadata.setContentLength(bytes.length);
        // Set the crypto instruction file header
        metadata.addUserMetadata(."");
        // Update the instruction request
        req.setMetadata(metadata);
        req.setInputStream(new ByteArrayInputStream(bytes));
        // the file attribute in the request is always null before calling this
        // routine
        return req;
    }
            String bucketNameString keyContentCryptoMaterial cekMaterial) {
        byte[] bytes = cekMaterial.toJsonString(.getCryptoMode())
                                  .getBytes();
        InputStream is = new ByteArrayInputStream(bytes);
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(bytes.length);
        metadata.addUserMetadata(."");
        InstructionFileId ifileId = new S3ObjectId(bucketNamekey)
                .instructionFileId();
        return new PutObjectRequest(ifileId.getBucket(), ifileId.getKey(),
            ismetadata);
    }

    
Appends a user agent to the request's USER_AGENT client marker. This method is intended only for internal use by the AWS SDK.
    final <X extends AmazonWebServiceRequest> X appendUserAgent(
            X requestString userAgent) {
        request.getRequestClientOptions().appendUserAgent(userAgent);
        return request;
    }

    
Checks if the the crypto scheme used in the given content crypto material is allowed to be used in this crypto module. Default is no-op. Subclass may override.

Throws:
java.lang.SecurityException if the crypto scheme used in the given content crypto material is not allowed in this crypto module.
    protected void securityCheck(ContentCryptoMaterial cekMaterial,
            S3ObjectWrapper retrieved) {
    }

    
Retrieves an instruction file from S3; or null if no instruction file is found.

Parameters:
s3ObjectId the S3 object id (not the instruction file id)
instFileSuffix suffix of the instruction file to be retrieved; or null to use the default suffix.
Returns:
an instruction file, or null if no instruction file is found.
            String instFileSuffix) {
        try {
            S3Object o = .getObject(
                createInstructionGetRequest(s3ObjectIdinstFileSuffix));
            return o == null ? null : new S3ObjectWrapper(os3ObjectId);
        } catch (AmazonServiceException e) {
            // If no instruction file is found, log a debug message, and return
            // null.
            if (.isDebugEnabled()) {
                .debug("Unable to retrieve instruction file : "
                        + e.getMessage());
            }
            return null;
        }
    }
    @Override
            PutInstructionFileRequest req) {
        final S3ObjectId id = req.getS3ObjectId();
        final GetObjectRequest getreq = new GetObjectRequest(id);
        appendUserAgent(getreq);
        // Get the object from S3
        final S3Object retrieved = .getObject(getreq);
        // We only need the meta-data already retrieved, not the data stream.
        // So close it immediately to prevent resource leakage.
        closeQuietly(retrieved);
        if (retrieved == null) {
            throw new IllegalArgumentException(
                    "The specified S3 object (" + id + ") doesn't exist.");
        }
        S3ObjectWrapper wrapped = new S3ObjectWrapper(retrievedid);
        try {
            final ContentCryptoMaterial origCCM = contentCryptoMaterialOf(wrapped);
            if (..equals(origCCM.getContentCryptoScheme())
            &&  .getCryptoMode() == .) {
                throw new SecurityException(
                    "Lowering the protection of encryption material is not allowed");
            }
            securityCheck(origCCMwrapped);
            // Re-ecnrypt the CEK in a new content crypto material
            final EncryptionMaterials newKEK = req.getEncryptionMaterials();
            final ContentCryptoMaterial newCCM;
            if (newKEK == null) {
                newCCM = origCCM.recreate(req.getMaterialsDescription(),
                        this.,
                        ,
                        .getCryptoProvider(), req);
            } else {
                newCCM = origCCM.recreate(newKEK,
                        this.,
                        ,
                        .getCryptoProvider(), req);
            }
            PutObjectRequest putInstFileRequest = req.createPutObjectRequest(retrieved);
            // Put the new instruction file into S3
            return .putObject(updateInstructionPutRequest(putInstFileRequestnewCCM));
        } catch (RuntimeException ex) {
            // If we're unable to set up the decryption, make sure we close the
            // HTTP connection
            closeQuietly(retrieved);
            throw ex;
        } catch (Error error) {
            closeQuietly(retrieved);
            throw error;
        }
    }

    
Returns the content crypto material of an existing S3 object.

Parameters:
s3w an existing S3 object (wrapper)
s3objectId the object id used to retrieve the existing S3 object
Returns:
a non-null content crypto material.
        // Check if encryption info is in object metadata
        if (s3w.hasEncryptionInfo()) {
            return ContentCryptoMaterial
                .fromObjectMetadata(s3w.getObjectMetadata(),
                    ,
                    .getCryptoProvider(),
                    false,   // existing CEK not necessarily key-wrapped
                    
                );
        }
        S3ObjectWrapper orig_ifile =
            fetchInstructionFile(s3w.getS3ObjectId(), null);
        if (orig_ifile == null) {
            throw new IllegalArgumentException(
                "S3 object is not encrypted: " + s3w);
        }
        if (!orig_ifile.isInstructionFile()) {
            throw new AmazonClientException(
                "Invalid instruction file for S3 object: " + s3w);
        }
        String json = orig_ifile.toJsonString();
        return ccmFromJson(json);
    }
    private ContentCryptoMaterial ccmFromJson(String json) {
        @SuppressWarnings("unchecked")
        Map<StringStringinstruction = Collections.unmodifiableMap(
                Jackson.fromJsonString(jsonMap.class));
        return ContentCryptoMaterial.fromInstructionFile(
            instruction,
            ,
            .getCryptoProvider(),
            false,   // existing CEK not necessarily key-wrapped
            
        );
    }

    
Creates a get object request for an instruction file using the default instruction file suffix.

Parameters:
id an S3 object id (not the instruction file id)
Returns:
A get request to retrieve an instruction file from S3.
        return createInstructionGetRequest(idnull);
    }

    
Creates and return a get object request for an instruction file.

Parameters:
s3objectId an S3 object id (not the instruction file id)
instFileSuffix suffix of the specific instruction file to be used, or null if the default instruction file is to be used.
            S3ObjectId s3objectIdString instFileSuffix) {
        return new GetObjectRequest(
                s3objectId.instructionFileId(instFileSuffix));
    }
    static long[] getAdjustedCryptoRange(long[] range) {
        // If range is invalid, then return null.
        if (range == null || range[0] > range[1]) {
            return null;
        }
        long[] adjustedCryptoRange = new long[2];
        adjustedCryptoRange[0] = getCipherBlockLowerBound(range[0]);
        adjustedCryptoRange[1] = getCipherBlockUpperBound(range[1]);
        return adjustedCryptoRange;
    }
    private static long getCipherBlockLowerBound(long leftmostBytePosition) {
        long cipherBlockSize = .;
        long offset = leftmostBytePosition % cipherBlockSize;
        long lowerBound = leftmostBytePosition - offset - cipherBlockSize;
        return lowerBound < 0 ? 0 : lowerBound;
    }

    
Takes the position of the rightmost desired byte of a user specified range and returns the position of the end of the following cipher block; or java.lang.Long.MAX_VALUE if the resultant position has a value that exceeds java.lang.Long.MAX_VALUE.
    private static long getCipherBlockUpperBound(final long rightmostBytePosition) {
        long cipherBlockSize = .;
        long offset = cipherBlockSize - (rightmostBytePosition % cipherBlockSize);
        long upperBound = rightmostBytePosition + offset + cipherBlockSize;
        return upperBound < 0 ? . : upperBound;
    }
New to GrepCode? Check out our FAQ X