Signature V4 AWS S3 Put C#


        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            fnPutObject();
        }

        string ToHex(byte[] array)
        {
            string strOutput = "";
            for (int i = 0; i < array.Length; i++)
            {
                strOutput += $"{array[i]:x2}";
            }
            return strOutput;
        }

        byte[] HmacSHA256(String data, byte[] key)
        {
            String algorithm = "HmacSHA256";
            KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
            kha.Key = key;

            return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
        }

        byte[] HashFromString(String data)
        {
            String algorithm = "SHA256";
            HashAlgorithm ha = HashAlgorithm.Create(algorithm);
            return ha.ComputeHash(Encoding.UTF8.GetBytes(data));
        }

        byte[] HashFromByte(Byte[] data)
        {
            String algorithm = "SHA256";
            HashAlgorithm ha = HashAlgorithm.Create(algorithm);
            return ha.ComputeHash(data);
        }

        byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName)
        {
            byte[] kSecret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray());
            byte[] kDate = HmacSHA256(dateStamp, kSecret);
            byte[] kRegion = HmacSHA256(regionName, kDate);
            byte[] kService = HmacSHA256(serviceName, kRegion);
            byte[] kSigning = HmacSHA256("aws4_request", kService);

            return kSigning;
        }

        void fnPutObject()
        {
            string strAccessKey = "";
            string strSecretKey = "";
            DateTime dt;
            dt = DateTime.UtcNow;
            string amzdate = dt.ToString("yyyyMMddTHHmmssZ");
            string strDate = dt.ToString("yyyyMMdd");
            string strMethod = "PUT";
            string strService = "s3";
            string strBucketName = "jeff";
            string strHost = strBucketName + "." + strService + ".amazonaws.com";
            string strRegion = "us-east-1";
            string strContentName = "myfile.txt";
            var byteContent = Encoding.UTF8.GetBytes("Hello World!");
            string strContentType = "text/plain";
            //string strAcl = "public-read";  //If no acl provided, private is used
            string strPayloadHash = ToHex(HashFromByte(byteContent));

            //Headers
            Dictionary<<string, string> dictRequestHeaders = new Dictionary<string, string>();
            dictRequestHeaders.Add("Content-Type", strContentType);
            dictRequestHeaders.Add("Host", strHost);
            //dictRequestHeaders.Add("x-amz-acl", strAcl);
            dictRequestHeaders.Add("x-amz-content-sha256", strPayloadHash);
            dictRequestHeaders.Add("x-amz-date", amzdate);

            var lstCanonicalHeaders = new List<string>();
            foreach (var item in dictRequestHeaders)
            {
                lstCanonicalHeaders.Add(item.Key.ToLower() + ":" + item.Value);
            }
            string strCanonicalHeaders = String.Join("\n", lstCanonicalHeaders.ToArray());

            var lstSignedHeaders = new List<string>();
            foreach (var item in dictRequestHeaders)
            {
                lstSignedHeaders.Add(item.Key.ToLower());
            }
            string strSignedHeaders = String.Join(";", lstSignedHeaders.ToArray());

            //Canonical Request
            var lstCanonicalRequest = new List<string>();
            lstCanonicalRequest.Add(strMethod);
            lstCanonicalRequest.Add("/" + strContentName);
            lstCanonicalRequest.Add("");
            lstCanonicalRequest.Add(strCanonicalHeaders);
            lstCanonicalRequest.Add("");
            lstCanonicalRequest.Add(strSignedHeaders);
            lstCanonicalRequest.Add(strPayloadHash);
            string strCanonicalRequest = String.Join("\n", lstCanonicalRequest.ToArray());
            string strHashedCanonicalRequest = ToHex(HashFromString(strCanonicalRequest));

            //Scope
            var lstScope = new List<string>();
            lstScope.Add(strDate);
            lstScope.Add(strRegion);
            lstScope.Add(strService);
            lstScope.Add("aws4_request");

            //String To Sign
            var lstStringToSign = new List<string>();
            lstStringToSign.Add("AWS4-HMAC-SHA256");
            lstStringToSign.Add(amzdate);
            lstStringToSign.Add(String.Join("/", lstScope.ToArray()));
            lstStringToSign.Add(strHashedCanonicalRequest);
            string strStringToSign = String.Join("\n", lstStringToSign.ToArray());

            //Signature
            byte[] byteSigningKey = getSignatureKey(strSecretKey, strDate, strRegion, strService);
            byte[] byteSignature = HmacSHA256(strStringToSign, byteSigningKey);

            string strAuthorization = "AWS4-HMAC-SHA256" + " " + "Credential=" + strAccessKey + "/" + String.Join("/", lstScope.ToArray()) + ", " + "SignedHeaders=" + strSignedHeaders + ", " + "Signature=" + ToHex(byteSignature);

            string strResponse = "";
            HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create("https://" + strHost + "/" + strContentName);
            try
            {
                webReq.Headers.Add("Authorization", strAuthorization);
                webReq.ContentType = strContentType;
                webReq.Host = strHost;
                foreach (var item in dictRequestHeaders)
                {
                    if (item.Key.ToLower() != "content-type" AND item.Key.ToLower() != "host")
                    {
                        System.Diagnostics.Debug.WriteLine(item.Key.ToLower());
                        webReq.Headers.Add(item.Key, item.Value);
                    }
                    
                }
                webReq.Method = strMethod;
                Stream dataStream = webReq.GetRequestStream();
                dataStream.Write(byteContent, 0, byteContent.Length);
                dataStream.Close();
                using (WebResponse response = webReq.GetResponse())
                {
                    using (Stream stream = response.GetResponseStream())
                    {
                        StreamReader reader = new StreamReader(stream);
                        strResponse = reader.ReadToEnd();
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }

            System.Diagnostics.Debug.WriteLine(strResponse);
        }