pub fn sign(&mut self, creds: &AwsCredentials) {
        self.complement();
        let date = Utc::now();
        self.remove_header("x-amz-date");
        self.add_header("x-amz-date", &date.format("%Y%m%dT%H%M%SZ").to_string());

        if let Some(ref token) = *creds.token() {
            self.remove_header("X-Amz-Security-Token");
            self.add_header("X-Amz-Security-Token", token);
        }

        let digest = match self.payload {
            None => Cow::Borrowed(EMPTY_SHA256_HASH),
            Some(SignedRequestPayload::Buffer(ref payload)) => {
                let (digest, _) = digest_payload(&payload);
                Cow::Owned(digest)
            }
            Some(SignedRequestPayload::Stream(_)) => Cow::Borrowed(UNSIGNED_PAYLOAD),
        };
        self.remove_header("x-amz-content-sha256");
        self.add_header("x-amz-content-sha256", &digest);

        let signed_headers = signed_headers(&self.headers);

        let canonical_headers = canonical_headers(&self.headers);

        // Normalize URI paths according to RFC 3986. Remove redundant and relative path components. Each path segment must be URI-encoded twice (except for Amazon S3 which only gets URI-encoded once).
        // see https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
        let canonical_uri = if &self.service != "s3" {
            utf8_percent_encode(&self.canonical_uri, &STRICT_PATH_ENCODE_SET).collect::<String>()
        } else {
            self.canonical_uri.clone()
        };

        let canonical_request = format!(
            "{}\n{}\n{}\n{}\n{}\n{}",
            &self.method,
            canonical_uri,
            self.canonical_query_string,
            canonical_headers,
            signed_headers,
            digest
        );

        // use the hashed canonical request to build the string to sign
        let hashed_canonical_request = to_hexdigest(&canonical_request);
        let scope = format!(
            "{}/{}/{}/aws4_request",
            date.format("%Y%m%d"),
            &self.region_for_service(),
            &self.service
        );
        let string_to_sign = string_to_sign(date, &hashed_canonical_request, &scope);

        // sign the string
        let signature = sign_string(
            &string_to_sign,
            creds.aws_secret_access_key(),
            date.date().naive_utc(),
            &self.region_for_service(),
            &self.service,
        );

        // build the actual auth header
        let auth_header = format!(
            "AWS4-HMAC-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}",
            &creds.aws_access_key_id(),
            scope,
            signed_headers,
            signature
        );
        self.remove_header("authorization");
        self.add_header("authorization", &auth_header);
    }
Signs the request using Amazon Signature version 4 to verify identity.
Authorization header uses AWS4-HMAC-SHA256 for signing.
rusoto/signature/src/signature.rs