**Use case**
With S3, you have to send the header `x-amz-server-side-encryption-customer-key` and `x-amz-server-side-encryption-customer-key-md5` if the resource is server side encrypted.

https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeysSSEUsingRESTAPI.html
https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerSideEncryptionCustomerKeys.html

**Describe the solution you'd like**
Ability to set this in the query.
Strings result;
    Aws::S3::Model::ListObjectsV2Outcome outcome;
    int page = 0;
    do
    {
        ++page;
        outcome = client.ListObjectsV2(request);
        if (!outcome.IsSuccess())
        {
            if (page > 1)
                throw Exception(ErrorCodes::S3_ERROR, "Could not list objects in bucket {} with prefix {}, page {}, S3 exception: {}, message: {}",
                            quoteString(request.GetBucket()), quoteString(request.GetPrefix()), page,
                            backQuote(outcome.GetError().GetExceptionName()), quoteString(outcome.GetError().GetMessage()));
            throw Exception(ErrorCodes::S3_ERROR, "Could not list objects in bucket {} with prefix {}, S3 exception: {}, message: {}",
                            quoteString(request.GetBucket()), quoteString(request.GetPrefix()),
                            backQuote(outcome.GetError().GetExceptionName()), quoteString(outcome.GetError().GetMessage()));
        }
        for (const auto & row : outcome.GetResult().GetContents())
        {
            String key = row.GetKey();
            if (re2::RE2::FullMatch(key, matcher))
                result.emplace_back(std::move(key));
        }
        request.SetContinuationToken(outcome.GetResult().GetNextContinuationToken());
    }
    while (outcome.GetResult().GetIsTruncated());
    return result;
}
}
Pipe StorageS3::read(