override fun signURL()

in apps/chat-android/messaging-websocket/src/main/java/com/amazonaws/services/chime/sdk/messaging/utils/DefaultSigV4.kt [25:119]


    override fun signURL(
        method: String,
        scheme: String,
        serviceName: String,
        hostname: String,
        path: String,
        payload: String,
        queryParams: Map<String, List<String>>?
    ): String {
        val now = getDateTimeString()
        val today = getDateString(now)

        val algorithm = "AWS4-HMAC-SHA256"
        val signedHeaders = "host"
        val canonicalHeaders = "host:${hostname.toLowerCase(Locale.getDefault())}\n"
        val credentialScope = "$today/$region/$serviceName/aws4_request"

        var params = mutableMapOf<String, MutableList<String>>().apply {
            set("X-Amz-Algorithm", mutableListOf(algorithm))
            set(
                "X-Amz-Credential", mutableListOf(
                    encodeURIComponent("${credentials.accessKeyId}/$credentialScope")
                )
            )
            set("X-Amz-Date", mutableListOf(now))
            set("X-Amz-Expires", mutableListOf("10"))
            set("X-Amz-SignedHeaders", mutableListOf("host"))
            credentials.sessionToken?.let {
                set("X-Amz-Security-Token", mutableListOf(encodeURIComponent(it)))
            }
        }

        if (queryParams != null) {
            for ((key, values) in queryParams) {
                val encodedKey = encodeURIComponent(key)
                values.sorted()
                values.forEach {
                    if (!params.containsKey(encodedKey)) {
                        params[encodedKey] = mutableListOf()
                    }
                    params[encodedKey]?.add(encodeURIComponent(it))
                }
            }
        }

        val canonicalQueryStringBuilder = StringBuilder()
        // Query string has to be sorted by parameters
        params = params.toSortedMap()
        params.forEach { (key, values) ->
            values.forEach { value ->
                if (canonicalQueryStringBuilder.isNotEmpty()) {
                    canonicalQueryStringBuilder.append("&")
                }
                canonicalQueryStringBuilder.append(key)
                canonicalQueryStringBuilder.append("=")
                canonicalQueryStringBuilder.append(value)
            }
        }
        val canonicalQueryString = canonicalQueryStringBuilder.toString()

        val canonicalRequest =
            method +
                    "\n" +
                    path +
                    "\n" +
                    canonicalQueryString +
                    "\n" +
                    canonicalHeaders +
                    "\n" +
                    signedHeaders +
                    "\n" +
                    hex(sha256(payload))

        val hashedCanonicalRequest = hex(sha256(canonicalRequest))

        val stringToSign =
            "AWS4-HMAC-SHA256\n" +
                    now +
                    "\n" +
                    today +
                    "/" +
                    region +
                    "/" +
                    serviceName +
                    "/aws4_request\n" +
                    hashedCanonicalRequest

        val signingKey = getSignatureKey(credentials.secretAccessKey, today, region, serviceName)

        val signature = hex(hmac(stringToSign, signingKey))

        val finalParams = "$canonicalQueryString&X-Amz-Signature=$signature"

        return "$scheme://$hostname$path?$finalParams"
    }