### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

TL;DR: When presigned URL contains one of `Content-MD5`, `X-AMZ-Server-Side-Encryption` headers or their combination, it does not work on localstack, but works in AWS. 

The **presigned S3 URL feature** allows to **add additional headers** to the request when using the **Version 4** signature. These headers are then used in the signing mechanism and verified when such URL is used.

**Use case**: When generating an URL to PUT a file into S3 bucket using the `aws-sdk` Node.js API, I add the MD5 hash of the file-to-be-uploaded to ensure the integrity and say that server-side-encryption should be used. Note that these arguments are added through the native options of `aws-sdk` API:

```js
const s3 = new AWS.S3({
  endpoint: 'http://localhost:4566',
  signatureVersion: 'v4', // Required for the presigned URL functionality with extra headers
  s3ForcePathStyle: true, // Do not use custom domains
});

const body = '123456';
const bodyMd5AsBase64 = '4QrcOUm6Wau+VuBX8g+IPg=='

const url = await s3.getSignedUrlPromise('putObject', {
  Bucket: 'test-bucket',
  Key: 'test-file',
  Expires: 3600,
  ServerSideEncryption: 'AES256', // Adds 'X-Amz-Server-Side-Encryption' in query string
  ContentMD5: bodyMD5             // Adds 'Content-MD5' parameter in query string
});

// url: http://localhost:4566/testBucket/testFile
//   ?Content-MD5=4QrcOUm6Wau%2BVuBX8g%2BIPg%3D%3D
//   &X-Amz-Algorithm=AWS4-HMAC-SHA256
//   &X-Amz-Credential=test%2F20220113%2Fus-east-1%2Fs3%2Faws4_request
//   &X-Amz-Date=20220113T142952Z
//   &X-Amz-Expires=3600
//   &X-Amz-Signature=d219a729f06e37d40a136bb5fec777265b1b34e879f9e338d385b39a3760a14f
//   &X-Amz-SignedHeaders=content-md5%3Bhost%3Bx-amz-server-side-encryption
//   &x-amz-server-side-encryption=AES256
//
// NOTE X-Amz-SignedHeaders contains `content-md5` and `x-amz-server-side-encryption` keys as well

const result = await fetch(url, {
  method: 'PUT',
  body: body,
  headers: {
    'Content-Type': 'text/plain',
    'Accept': 'application/json',
    'Content-MD5': bodyMD5, // This is required, otherwise AWS refuses to accept the request
    'x-amz-server-side-encryption': 'AES256' // This is optional, but AWS is okay when value is passed as both query argument and header with same value
  },
});
```

This example shows few issues, which are present when trying to process various presigned requests in localstack, but work correctly in AWS. I try to list them one by one below:

**Issue 1: Allow X-AMZ-Server-Side-Encryption in query string**

Presigned URL query string contains `x-amz-server-side-encryption=AES256` and `X-Amz-Signed-Headers=host%3Bx-amz-server-side-encryption`

PUT request does not contain any extra headers.

Localstack fails to process the request. AWS works.

**Issue 2: Allow X-AMZ-Server-Side-Encryption in query string and PUT request header with same value**

Presigned URL query string contains `x-amz-server-side-encryption=AES256` and `X-Amz-Signed-Headers=host%3Bx-amz-server-side-encryption`

PUT request does contains extra header `x-amz-server-side-encryption=AES256`.

Localstack fails to process the request. AWS works.

**Issue 3: Allow Content-MD5 in query string and PUT request header with same value**

Presigned URL query string contains `Content-MD5=...` and `X-Amz-Signed-Headers=content-md5%3Bhost`

PUT request does contains extra header `Content-MD5=...`.

Localstack fails to process the request. AWS works.

**Issue 4: Allow Content-MD5 and X-AMZ-Server-Side-Encryption in same request**

Combination of issues above. Localstack fails to process the request. AWS works.

### Expected Behavior

_No response_

### How are you starting LocalStack?

With a docker-compose file

### Steps To Reproduce

I spin up the localstack docker with arguments below. Just noting that in its simple form, I was able to generate and successfully verify the presigned requests; so it's not an issue of invalid configuration.
```
S3_SKIP_SIGNATURE_VALIDATION=0
AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test`
```

1. Assume you have running Node.js (tested on v12) and Docker.
2. Extract archive [presigned-urls-test.zip](https://github.com/localstack/localstack/files/7863686/presigned-urls-test.zip) and `cd` to this folder
3. `npm install` to install the `aws-sdk` dependency
3. `npm run docker` to spin up the localstack. It will listen on `localhost:4566`
4. `npm run test` to run the test
5. The file should end up with `200` response code in output, but it fails on `403` signature mismatch.


### Environment

```markdown
- OS: Ubuntu 20.04
- Localstack: 0.13.3
- Node.js: 12
- Docker
```


### Anything else?

Signature V4 specification: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html

It seems to me the error is somewhere inside `authenticate_presign_url` method in here

https://github.com/localstack/localstack/blob/a400de0982487df33ae7c7cfc6d255839a03d91e/localstack/services/s3/s3_utils.py#L220-L253

I am not a Python developer, but I have suspicion, that:
* `X-Amz-SignedHeaders` query argument is not parsed to see which extra headers should be included for the signature verification, resulting in `Content-MD5` being skipped
* there is something strange when header with same value is present in both query string and request headers (such as the `Content-MD5` that is neccessary to pass in both, or `X-Amz-Server-Side-Encryption`, that is neccessary to be just in the query string, but AWS allows it to be ALSO in request headers with same value)

Maybe my assumptions are wrong, I was not investigating the code that much.

Hopefully this helps to describe the issue. I know that 
self, s3_client, s3_bucket, patch_s3_skip_signature_validation_false
    ):
        """related to issue: https://github.com/localstack/localstack/issues/4133"""
        def add_query_param(request, **kwargs):
            request.url += "?requestedBy=abcDEF123"
        s3_client.put_(Body="test-value", Bucket=s3_bucket, Key="test")
        s3_presigned_client = _s3_client_custom_config(
            Config(signature_version="s3v4"),
            endpoint_url=_endpoint_url(),
        )
        s3_presigned_client.meta.events.register("before-sign.s3.GetObject", add_query_param)
        try:
            presign_url = s3_presigned_client.generate_presigned_url(
                ClientMethod="get_",
                Params={"Bucket": s3_bucket, "Key": "test"},
                ExpiresIn=86400,
            )
            assert "requestedBy=abcDEF123" in presign_url
            response = .get(presign_url)
            assert b"test-value" == response._content
        finally:
            s3_presigned_client.meta.events.unregister("before-sign.s3.GetObject", add_query_param)
    @pytest.mark.only_localstack
    @pytest.mark.xfail(
        condition=not LEGACY_S3_PROVIDER,
        reason="failing for ASF provider, will be fixed in separate PR",
    )
    def test_presign_check_signature_validation_for_port_permutation(