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.CryptoMode.AuthenticatedEncryption;
 import static com.amazonaws.services.s3.model.CryptoMode.StrictAuthenticatedEncryption;
 import static com.amazonaws.services.s3.model.ExtraMaterialsDescription.NONE;
 import static com.amazonaws.util.IOUtils.closeQuietly;
 
 import java.io.File;
 import java.util.Map;
 
Authenticated encryption (AE) cryptographic module for the S3 encryption client.
 
     static {
         // Enable bouncy castle if available
         CryptoRuntime.enableBouncyCastle();
     }
    

Parameters:
cryptoConfig a read-only copy of the crypto configuration.
 
             AWSCredentialsProvider credentialsProvider,
             EncryptionMaterialsProvider encryptionMaterialsProvider,
             CryptoConfiguration cryptoConfig) {
         super(kmss3credentialsProviderencryptionMaterialsProvider,
                 cryptoConfig);
         CryptoMode mode = cryptoConfig.getCryptoMode();
         if (mode != 
         &&  mode != ) {
             throw new IllegalArgumentException();
         }
     }

    
Used for testing purposes only.
 
             EncryptionMaterialsProvider encryptionMaterialsProvider,
             CryptoConfiguration cryptoConfig) {
         this(nulls3new DefaultAWSCredentialsProviderChain(),
                 encryptionMaterialsProvidercryptoConfig);
     }
    
Used for testing purposes only.
 
             EncryptionMaterialsProvider encryptionMaterialsProvider,
             CryptoConfiguration cryptoConfig) {
         this(kmss3new DefaultAWSCredentialsProviderChain(),
                 encryptionMaterialsProvidercryptoConfig);
     }

    
Returns true if a strict encryption mode is in use in the current crypto module; false otherwise.
 
    protected boolean isStrict() {
        return false;
    }
    @Override
        appendUserAgent(req);
        // Adjust the crypto range to retrieve all of the cipher blocks needed to contain the user's desired
        // range of bytes.
        long[] desiredRange = req.getRange();
        if (isStrict() && desiredRange  != null)
            throw new SecurityException("Range get is not allowed in strict crypto mode");
        long[] adjustedCryptoRange = getAdjustedCryptoRange(desiredRange);
        if (adjustedCryptoRange != null)
            req.setRange(adjustedCryptoRange[0], adjustedCryptoRange[1]);
        // Get the object from S3
        S3Object retrieved = .getObject(req);
        // If the caller has specified constraints, it's possible that super.getObject(...)
        // would return null, so we simply return null as well.
        if (retrieved == null)
            return null;
        String suffix = null;
        if (req instanceof EncryptedGetObjectRequest) {
            EncryptedGetObjectRequest ereq = (EncryptedGetObjectRequest)req;
            suffix = ereq.getInstructionFileSuffix();
        }
        try {
            return suffix == null || suffix.trim().isEmpty()
             ? decipher(reqdesiredRangeadjustedCryptoRangeretrieved)
             : decipherWithInstFileSuffix(req,
                     desiredRangeadjustedCryptoRangeretrieved,
                     suffix)
             ;
        } 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;
        }
    }
    private S3Object decipher(GetObjectRequest req,
            long[] desiredRangelong[] cryptoRange,
            S3Object retrieved) {
        S3ObjectWrapper wrapped = new S3ObjectWrapper(retrievedreq.getS3ObjectId());
        // Check if encryption info is in object metadata
        if (wrapped.hasEncryptionInfo())
            return decipherWithMetadata(reqdesiredRangecryptoRangewrapped);
        // Check if encrypted info is in an instruction file
        S3ObjectWrapper ifile = fetchInstructionFile(req.getS3ObjectId(), null);
        if (ifile != null) {
            try {
                if (ifile.isInstructionFile()) {
                    return decipherWithInstructionFile(reqdesiredRange,
                            cryptoRangewrappedifile);
                }
            } finally {
                closeQuietly(ifile);
            }
        }
        if (isStrict() || !.isIgnoreMissingInstructionFile()) {
            closeQuietly(wrapped);
            throw new SecurityException("Instruction file not found for S3 object with bucket name: "
                    + retrieved.getBucketName() + ", key: "
                    + retrieved.getKey());
        }
        // To keep backward compatible:
        // ignore the missing instruction file and treat the object as un-encrypted.
        .warn(String.format(
                "Unable to detect encryption information for object '%s' in bucket '%s'. "
                        + "Returning object without decryption.",
                retrieved.getKey(),
                retrieved.getBucketName()));
        // Adjust the output to the desired range of bytes.
        S3ObjectWrapper adjusted = adjustToDesiredRange(wrappeddesiredRangenull);
        return adjusted.getS3Object();
    }

    
Same as decipher(com.amazonaws.services.s3.model.GetObjectRequest,long[],long[],com.amazonaws.services.s3.model.S3Object) but makes use of an instruction file with the specified suffix.

Parameters:
instFileSuffix never null or empty (which is assumed to have been sanitized upstream.)
            long[] desiredRangelong[] cryptoRangeS3Object retrieved,
            String instFileSuffix) {
        final S3ObjectId id = req.getS3ObjectId();
        // Check if encrypted info is in an instruction file
        final S3ObjectWrapper ifile = fetchInstructionFile(idinstFileSuffix);
        if (ifile == null) {
            throw new AmazonClientException("Instruction file with suffix "
                    + instFileSuffix + " is not found for " + retrieved);
        }
        try {
            if (ifile.isInstructionFile()) {
                return decipherWithInstructionFile(reqdesiredRange,
                        cryptoRangenew S3ObjectWrapper(retrievedid), ifile);
            } else {
                throw new AmazonClientException(
                        "Invalid Instruction file with suffix "
                                + instFileSuffix + " detected for " + retrieved);
            }
        } finally {
            closeQuietly(ifile);
        }
    }
            long[] desiredRangelong[] cryptoRangeS3ObjectWrapper retrieved,
            S3ObjectWrapper instructionFile) {
        ExtraMaterialsDescription extraMatDesc = ;
        boolean keyWrapExpected = isStrict();
        if (req instanceof EncryptedGetObjectRequest) {
            EncryptedGetObjectRequest ereq = (EncryptedGetObjectRequest)req;
            extraMatDesc = ereq.getExtraMaterialDescription();
            if (!keyWrapExpected)
                keyWrapExpected = ereq.isKeyWrapExpected();
        }
        String json = instructionFile.toJsonString();
        @SuppressWarnings("unchecked")
        Map<StringStringmatdesc =
            Collections.unmodifiableMap(Jackson.fromJsonString(jsonMap.class));
        ContentCryptoMaterial cekMaterial =
                ContentCryptoMaterial.fromInstructionFile(
                    matdesc,
                    ,
                    .getCryptoProvider(), 
                    cryptoRange,   // range is sometimes necessary to compute the adjusted IV
                    extraMatDesc,
                    keyWrapExpected,
                    
            );
        securityCheck(cekMaterialretrieved);
        S3ObjectWrapper decrypted = decrypt(retrievedcekMaterialcryptoRange);
        // Adjust the output to the desired range of bytes.
        S3ObjectWrapper adjusted = adjustToDesiredRange(
                decrypteddesiredRangematdesc);
        return adjusted.getS3Object();
    }
            long[] desiredRange,
            long[] cryptoRangeS3ObjectWrapper retrieved) {
        ExtraMaterialsDescription extraMatDesc = ;
        boolean keyWrapExpected = isStrict();
        if (req instanceof EncryptedGetObjectRequest) {
            EncryptedGetObjectRequest ereq = (EncryptedGetObjectRequest)req;
            extraMatDesc = ereq.getExtraMaterialDescription();
            if (!keyWrapExpected)
                keyWrapExpected = ereq.isKeyWrapExpected();
        }
        ContentCryptoMaterial cekMaterial = ContentCryptoMaterial
            .fromObjectMetadata(retrieved.getObjectMetadata(),
                ,
                .getCryptoProvider(),
                // range is sometimes necessary to compute the adjusted IV
                cryptoRange,
                extraMatDesc,
                keyWrapExpected,
                
            );
        securityCheck(cekMaterialretrieved);
        S3ObjectWrapper decrypted = decrypt(retrievedcekMaterialcryptoRange);
        // Adjust the output to the desired range of bytes.
        S3ObjectWrapper adjusted = adjustToDesiredRange(
                decrypteddesiredRangenull);
        return adjusted.getS3Object();
    }

    
Adjusts the retrieved S3Object so that the object contents contain only the range of bytes desired by the user. Since encrypted contents can only be retrieved in CIPHER_BLOCK_SIZE (16 bytes) chunks, the S3Object potentially contains more bytes than desired, so this method adjusts the contents range.

Parameters:
s3object The S3Object retrieved from S3 that could possibly contain more bytes than desired by the user.
range A two-element array of longs corresponding to the start and finish (inclusive) of a desired range of bytes.
instruction Instruction file in JSON or null if no instruction file is involved
Returns:
The S3Object with adjusted object contents containing only the range desired by the user. If the range specified is invalid, then the S3Object is returned without any modifications.
    protected final S3ObjectWrapper adjustToDesiredRange(S3ObjectWrapper s3object,
            long[] rangeMap<String,Stringinstruction) {
        if (range == null)
            return s3object;
        // Figure out the original encryption scheme used, which can be
        // different from the crypto scheme used for decryption.
        ContentCryptoScheme encryptionScheme = s3object.encryptionSchemeOf(instruction);
        // range get on data encrypted using AES_GCM
        final long instanceLen = s3object.getObjectMetadata().getInstanceLength();
        final long maxOffset = instanceLen - encryptionScheme.getTagLengthInBits() / 8 - 1;
        if (range[1] > maxOffset) {
            range[1] = maxOffset;
            if (range[0] > range[1]) {
                // Return empty content
                // First let's close the existing input stream to avoid resource
                // leakage
                closeQuietly(s3object.getObjectContent(), );
                s3object.setObjectContent(new ByteArrayInputStream(new byte[0]));
                return s3object;
            }
        }
        if (range[0] > range[1]) {
            // Make no modifications if range is invalid.
            return s3object;
        }
        try {
            S3ObjectInputStream objectContent = s3object.getObjectContent();
            InputStream adjustedRangeContents = new AdjustedRangeInputStream(objectContentrange[0], range[1]);
            s3object.setObjectContent(new S3ObjectInputStream(adjustedRangeContentsobjectContent.getHttpRequest()));
            return s3object;
        } catch (IOException e) {
            throw new AmazonClientException("Error adjusting output to desired byte range: " + e.getMessage());
        }
    }
    
    @Override
    public ObjectMetadata getObjectSecurely(GetObjectRequest getObjectRequest,
            File destinationFile) {
        assertParameterNotNull(destinationFile,
        "The destination file parameter must be specified when downloading an object directly to a file");
        S3Object s3Object = getObjectSecurely(getObjectRequest);
        // getObject can return null if constraints were specified but not met
        if (s3Object == nullreturn null;
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(destinationFile));
            byte[] buffer = new byte[1024*10];
            int bytesRead;
            while ((bytesRead = s3Object.getObjectContent().read(buffer)) > -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            throw new AmazonClientException(
                    "Unable to store object contents to disk: " + e.getMessage(), e);
        } finally {
            closeQuietly(outputStream);
            closeQuietly(s3Object.getObjectContent(), );
        }
        /*
         * Unlike the standard Amazon S3 Client, the Amazon S3 Encryption Client does not do an MD5 check
         * here because the contents stored in S3 and the contents we just retrieved are different.  In
         * S3, the stored contents are encrypted, and locally, the retrieved contents are decrypted.
         */
        return s3Object.getObjectMetadata();
    }
    @Override
            InitiateMultipartUploadRequest reqContentCryptoMaterial cekMaterial) {
        return new MultipartUploadCryptoContext(
                req.getBucketName(), req.getKey(), cekMaterial);
    }
    //// specific overrides for uploading parts.
    @Override
            MultipartUploadCryptoContext uploadContext) {
        return uploadContext.getCipherLite();
    }
    @Override
            CipherLiteInputStream  islong partSize) {
        return is;
    }
    @Override
    final long computeLastPartSize(UploadPartRequest req) {
        return req.getPartSize()
             + (.getTagLengthInBits() / 8);
    }
    @Override
    final void updateUploadContext(MultipartUploadCryptoContext uploadContext,
            SdkFilterInputStream is) {
    }
    /*
     * Private helper methods
     */

    
Returns an updated object where the object content input stream contains the decrypted contents.

Parameters:
wrapper The object whose contents are to be decrypted.
cekMaterial The instruction that will be used to decrypt the object data.
Returns:
The updated object where the object content input stream contains the decrypted contents.
    private S3ObjectWrapper decrypt(S3ObjectWrapper wrapper,
            ContentCryptoMaterial cekMateriallong[] range) {
        S3ObjectInputStream objectContent = wrapper.getObjectContent();
        wrapper.setObjectContent(new S3ObjectInputStream(
                new CipherLiteInputStream(objectContent
                    cekMaterial.getCipherLite(),
                    ),
                    objectContent.getHttpRequest()));
        return wrapper;
    }

    
Asserts that the specified parameter value is not null and if it is, throws an IllegalArgumentException with the specified error message.

Parameters:
parameterValue The parameter value being checked.
errorMessage The error message to include in the IllegalArgumentException if the specified parameter is null.
    private void assertParameterNotNull(Object parameterValueString errorMessage) {
        if (parameterValue == nullthrow new IllegalArgumentException(errorMessage);
    }
    @Override
    protected final long ciphertextLength(long originalContentLength) {
        // Add 16 bytes for the 128-bit tag length using AES/GCM
        return originalContentLength + .getTagLengthInBits()/8;
    }
New to GrepCode? Check out our FAQ X