Получение HTTPResponse
"{\" message \ ": \" Рассчитанная нами подпись запроса не соответствует
подпись вы предоставили. Проверьте свой секретный ключ доступа AWS и подпись
метод. Обратитесь к сервисной документации для деталей. \ N \ nThe
Каноническая строка для этого запроса должна иметь
был \ n'GET \ п / постановка / пользователь \ nemail = тест% 40gmail.com & мобильный = 123 \ naccess-ID: dffgdfgfgdfg \ nhost: dfgdfgdfgf \ ой-AMZ-дата: 20181113T134535Z \ ого-апи-ключ: \ N \ naccess -id, хозяин; х-АМЗ-дата, х-апи ключ \ "\ п \ NThe
Строка для подписи должна иметь
был \ n'AWS4-HMAC-SHA256 \ n20181113T134535Z \ n20181113 / ар-юго-восток-1 / выполнение-апи / aws4_request \ dfgdfgdfgdfgd '\ п \ "}"
Код: -
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace Test.Old_App_Code
{
public class APICall
{
public string CheckUserID()
{
UMSConfig oUMSConfig = new UMSConfig();
oUMSConfig.AccessId = "";
oUMSConfig.ApiKey = "";
oUMSConfig.Host = "";
oUMSConfig.RegionName = "";
oUMSConfig.SecretKey = "";
oUMSConfig.ServerName = "";
var authorization = new AwsHeaders(oUMSConfig, "/staging/user", "GET", "?email=test@gmail.com&mobile=123", "");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
WebRequest webRequest = WebRequest.Create("https://" + oUMSConfig.Host + "/staging/user?email=test@gmail.com&mobile=123");
webRequest.Method = "GET";
webRequest.ContentType = "application/json";
webRequest.Headers.Add("X-Amz-date", DateTime.Now.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"));
webRequest.Headers.Add("Authorization", authorization.Authorization);
webRequest.Headers.Add("x-api-key", oUMSConfig.ApiKey);
webRequest.Headers.Add("access-id", oUMSConfig.AccessId);
webRequest.UseDefaultCredentials = true;
webRequest.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
var response = (HttpWebResponse)webRequest.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return "";
}
}
public class AwsHeaders
{
public const string ENCRYPT_METHOD = "AWS4-HMAC-SHA256";
public string Host { get; private set; }
public string RequestUrl { get; private set; }
public string Authorization { get; private set; }
public IDictionary<string, string> AddtionalHeaders { get; set; }
public DateTime Date { get; private set; }
public DateTime DateVersion { get; set; }
public AwsHeaders(UMSConfig _config, string canonicalURI, string method, string queryString, string bodyPayload)
{
//setup info to generate headers
this.Host = _config.Host;
//aws will check this time for prevent over 5 minutes delay request
this.Date = DateTime.Now.ToUniversalTime();
this.DateVersion = DateTime.Now.ToUniversalTime();
//content headers key-val pair to add to HttpClient
this.AddtionalHeaders = new Dictionary<string, string>();
this.AddtionalHeaders.Add("access-id", _config.AccessId);
this.AddtionalHeaders.Add("host", _config.Host);
this.AddtionalHeaders.Add("x-amz-date", GetDateTimeString());
this.AddtionalHeaders.Add("x-api-key", _config.ApiKey);
//get HttpMethod name from enum
string httpRequestMethod = method.ToString();
//query string or body of request should be process then it should be empty string if it is null
var parsedQueryString = string.IsNullOrEmpty(queryString) ? "" : EncodeQueryString(queryString); //percent encode
bodyPayload = string.IsNullOrEmpty(bodyPayload) ? "" : bodyPayload;
//canonical headers are string combine of header-key:value+"\n" sorted by header key follow ASCII code
string canonicalHeaders = string.Join("\n", this.AddtionalHeaders.Select(a => a.Key + ":" + a.Value)) + "\n";
//signed headers are string combine of header-key join by "\n";
string signedHeaders = string.Join(";", this.AddtionalHeaders.Select(a => a.Key));
//hash the body by SHA256 then Encode it by Base16
var sha256 = SHA256.Create();
string hashPayload = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(bodyPayload))).Replace("-", "").ToLower();
//Canonical Request is string combine of HttpRequestMethod, CanonicalURI, percent encoded QueryString, CanonicalHeaders, SignedHeaders and Body Payload - JOIN by "\n"
//The canonical URI is the URI-encoded version of the absolute path component of the URI, which is everything in the URI from the HTTP host to the question mark character ("?") that begins the query string parameters (if any).
string canonicalRequest = httpRequestMethod + "\n" + canonicalURI + "\n" + parsedQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashPayload;
//Get Base16 encoded string of SHA256(CanonicalRequest)
//Use for build the Authorization Header
string hashedCanonicalRequest = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(canonicalRequest))).Replace("-", "").ToLower();
//Use for build the Authorization Header
string credentialScope = $"{GetDateVersionString()}/{_config.RegionName}/{_config.ServerName}/aws4_request";
//Use for build Signature
string stringToSign = AwsHeaders.ENCRYPT_METHOD + '\n'
+ GetDateTimeString() + '\n'
+ credentialScope + '\n' + hashedCanonicalRequest;
//transfer secretkey to derived signing key for security
byte[] derivedSigningKey = GetSignatureKey(_config.SecretKey, GetDateVersionString(), _config.RegionName, _config.ServerName);
//Get final Signature
string signature = BitConverter.ToString(HmacSHA256(stringToSign, derivedSigningKey)).Replace("-", "").ToLower();
string authorizationHeader = "Credential=" + _config.AccessId + "/" + credentialScope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature;
this.Authorization = AwsHeaders.ENCRYPT_METHOD + " " + authorizationHeader; //new AuthenticationHeaderValue(AwsHeaders.ENCRYPT_METHOD, authorizationHeader);
this.RequestUrl = $"{UMSConfig.HTTP_SCHEME}{_config.Host}{canonicalURI}";
if (!string.IsNullOrEmpty(queryString))
{
this.RequestUrl += $"?{queryString}";
}
}
private byte[] HmacSHA256(string data, byte[] key)
{
var hasher = new HMACSHA256(key);
return hasher.ComputeHash(Encoding.UTF8.GetBytes(data));
}
private 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;
}
private string EncodeQueryString(string query)
{
var keysVals = query.Split('&');
IDictionary<string, string> queries = new Dictionary<string, string>();
foreach (var kv in keysVals)
{
var splits = kv.Split('=');
var key = splits[0];
var val = splits[1];
if (!string.IsNullOrEmpty(val))
{
val = Uri.EscapeDataString(val);
}
queries.Add(key, val);
}
var encodedQuery = EncodeSpecialCharacters(string.Join("&", queries.OrderBy(q => q.Key).Select(v => Uri.EscapeDataString(v.Key) + (!string.IsNullOrEmpty(v.Value) ? "=" + v.Value : ""))));
return encodedQuery;
}
private string EncodeSpecialCharacters(string data)
{
//Do not URI-encode any of the unreserved characters that RFC 3986 defines: A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), and tilde ( ~ )
if (data.Contains("!"))
data = data.Replace("!", "%21");
if (data.Contains("'"))
data = data.Replace("'", "%27");
if (data.Contains("("))
data = data.Replace("(", "%28");
if (data.Contains(")"))
data = data.Replace(")", "%29");
if (data.Contains("*"))
data = data.Replace("*", "%2A");
if (data.Contains(","))
data = data.Replace(",", "%2C");
return data;
}
public string GetDateTimeString()
{
return this.Date.ToString("yyyyMMddTHHmmssZ");
}
public string GetDateVersionString()
{
return this.DateVersion.ToString("yyyyMMdd");
}
}
public class UMSConfig
{
public const string HTTP_SCHEME = "https://";
public string Host { get; set; }
public string Environment { get; set; }
public string AccessId { get; set; }
public string SecretKey { get; set; }
public string RegionName { get; set; }
public string ServerName { get; set; }
public string ApiKey { get; set; }
}
}