protected final S3ObjectWrapper adjustToDesiredRange(S3ObjectWrapper s3object,
                                                         long[] range, Map<String,String> instruction) {
        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(), log);
                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(objectContent, range[0], range[1]);
            s3object.setObjectContent(new S3ObjectInputStream(adjustedRangeContents, objectContent.getHttpRequest()));
            return s3object;
        } catch (IOException e) {
            throw new SdkClientException("Error adjusting output to desired byte range: " + e.getMessage());
        }
    }
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.

@param s3object
     The S3Object retrieved from S3 that could possibly contain more bytes than desired
     by the user.
@param range
     A two-element array of longs corresponding to the start and finish (inclusive) of a desired
     range of bytes.
@param instruction
     Instruction file in JSON or null if no instruction file is involved
@return
     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.
aws-java-sdk-s3/src/main/java/com/amazonaws/services/s3/internal/crypto/v2/S3CryptoModuleAE.java