private S3Object decipherWithInstructionFile(GetObjectRequest req,
            long[] desiredRange, long[] cryptoRange, S3ObjectWrapper retrieved,
            S3ObjectWrapper instructionFile) {
        ExtraMaterialsDescription extraMatDesc = NONE;
        boolean keyWrapExpected = isStrict();
        if (req instanceof EncryptedGetObjectRequest) {
            EncryptedGetObjectRequest ereq = (EncryptedGetObjectRequest)req;
            extraMatDesc = ereq.getExtraMaterialDescription();
            if (!keyWrapExpected)
                keyWrapExpected = ereq.isKeyWrapExpected();
        }
        String json = instructionFile.toJsonString();
        Map<String, String> matdesc =
            Collections.unmodifiableMap(Jackson.stringMapFromJsonString(json));
        ContentCryptoMaterial cekMaterial =
                ContentCryptoMaterial.fromInstructionFile(
                    matdesc,
                    kekMaterialsProvider,
                    cryptoConfig,
                    cryptoRange,   // range is sometimes necessary to compute the adjusted IV
                    extraMatDesc,
                    keyWrapExpected,
                    kms
            );
        boolean isRangeGet = desiredRange != null;
        securityCheck(cekMaterial, retrieved.getS3ObjectId(), isRangeGet);
        S3ObjectWrapper decrypted = decrypt(retrieved, cekMaterial, cryptoRange);
        // Adjust the output to the desired range of bytes.
        S3ObjectWrapper adjusted = adjustToDesiredRange(
                decrypted, desiredRange, matdesc);
        return adjusted.getS3Object();
    }
Same as {@link #decipher(GetObjectRequest, long[], long[], S3Object)}
but makes use of an instruction file with the specified suffix.
@param instFileSuffix never null or empty (which is assumed to have been
sanitized upstream.)
aws-java-sdk-s3/src/main/java/com/amazonaws/services/s3/internal/crypto/v2/S3CryptoModuleAE.java