C# AWS签名v4键值存储KVS在C中#
我试图在C#中集成“签名AWS请求与签名版本4”。不幸的是,Amazon并没有详细介绍C#的实现。我已经在实施中试过运气了。但是它抛出了这个错误信息 “远程服务器返回错误:(403)禁止 注意:我在《邮递员》上做了这项工作,但无法在C#中工作。 接收错误:Message=“远程服务器返回错误:(403)禁止。 我已使用此文档进行签名C# AWS签名v4键值存储KVS在C中#,c#,amazon-web-services,amazon-s3,aws-sdk,amazon-product-api,C#,Amazon Web Services,Amazon S3,Aws Sdk,Amazon Product Api,我试图在C#中集成“签名AWS请求与签名版本4”。不幸的是,Amazon并没有详细介绍C#的实现。我已经在实施中试过运气了。但是它抛出了这个错误信息 “远程服务器返回错误:(403)禁止 注意:我在《邮递员》上做了这项工作,但无法在C#中工作。 接收错误:Message=“远程服务器返回错误:(403)禁止。 我已使用此文档进行签名 publicwebrequest-RequestPost(字符串canonicalUri、字符串canonicalquerystring、字符串jsonString
publicwebrequest-RequestPost(字符串canonicalUri、字符串canonicalquerystring、字符串jsonString)
{
string hashedRequestPayload=CreateRequestPayload(jsonString);
字符串授权=符号(hashedRequestPayload,“PUT”、canonicalUri、CanonicalQueryString);
string requestDate=DateTime.ParseExact(DateTime.UtcNow.ToString(),“yyyyymmdd'T'HHMMSS'Z',CultureInfo.InvariantCulture).ToString();
WebRequest WebRequest=WebRequest.Create(canonicalUri+canonicalquerystring);
webRequest.Method=“PUT”;
webRequest.ContentType=ContentType;
webRequest.Headers.Add(“X-Amz-date”,requestDate);
webRequest.Headers.Add(“授权”,Authorization);
webRequest.Headers.Add(“x-amz-content-sha256”,hashedRequestPayload);
webRequest.ContentLength=jsonString.Length;
ascienceoding encoding=新的ascienceoding();
byte[]data=encoding.GetBytes(jsonString);
Stream newStream=webRequest.GetRequestStream();
newStream.Write(数据,0,数据长度);
使用(WebResponse=webRequest.GetResponse())
{
StreamReader responseReader=新的StreamReader(response.GetResponseStream());
var responseJson=responseReader.ReadToEnd();
}
返回webRequest;
}
常量字符串RegionName=“eu-west-1”//这是地区名称
常量字符串ServiceName=“执行api”;
常量字符串算法=“AWS4-HMAC-SHA256”;
const string ContentType=“应用程序/json”;
常量字符串主机=”;
const string SignedHeaders=“内容类型;主机;x-amz-content-sha256;x-amz-date”;
私有静态字符串CreateRequestPayload(字符串jsonString)
{
//这里应该是我们随POST请求发送的模型的JSON对象
//var jsonToSerialize=new{Data=String.Empty};
//如果发出GET请求,则将空字符串解析到序列化程序
//string requestPayload=new JavaScriptSerializer().Serialize(jsonToSerialize);
string hashedRequestPayload=HexEncode(Hash(ToBytes(jsonString));
返回hashedRequestPayload;
}
私有静态字符串符号(字符串hashedRequestPayload、字符串requestMethod、字符串canonicalUri、字符串canonicalQueryString)
{
var currentDateTime=DateTime.UtcNow;
var accessKey=“”;
var secretKey=“”;
var dateStamp=currentDateTime.ToString(“yyyyMMdd”);
//var requestDate=currentDateTime.ToString(“yyyyymmdd'T'HHMMSS'Z”);
var requestDate=DateTime.ParseExact(currentDateTime.ToString(),“yyyyymmdd'T'HHMMSS'Z',CultureInfo.InvariantCulture);
var credentialScope=string.Format(“{0}/{1}/{2}/aws4_请求”,日期戳,区域名称,服务名称);
var headers=新的SortedDictionary{
{“内容类型”,内容类型},
{“主机”,主机},
{“x-amz-date”,requestDate.ToString()}
};
string canonicalHeaders=string.Join(“\n”,headers.Select(x=>x.Key.ToLowerInvariant()+”:“+x.Value.Trim())+”\n”;
//任务1:为签名版本4创建规范请求
字符串canonicalRequest=requestMethod+“\n”+canonicalUri+“\n”+canonicalQueryString+“\n”+canonicalHeaders+“\n”+SignedHeaders+“\n”+hashedRequestPayload;
字符串hashedCanonicalRequest=HexEncode(Hash(ToBytes(canonicalRequest));
//任务2:为签名版本4创建要签名的字符串
字符串stringToSign=Algorithm+“\n”+requestDate+“\n”+credentialScope+“\n”+hashedCanonicalRequest;
//任务3:计算AWS签名版本4
字节[]signingKey=GetSignatureKey(secretKey、dateStamp、RegionName、ServiceName);
字符串签名=HexEncode(HmacSha256(stringToSign,signingKey));
//任务4:准备已签名的请求
//授权:算法凭据=访问密钥ID/凭据范围,SignedHeadaers=SignedHeaders,Signature=签名
string authorization=string.Format(“{0}凭证={1}/{2}/{3}/{4}/aws4_请求,SignedHeaders={5},Signature={6}”,
算法、accessKey、日期戳、RegionName、ServiceName、SignedHeader、签名);
退货授权;
}
私有静态字节[]GetSignatureKey(字符串键、字符串日期戳、字符串regionName、字符串serviceName)
{
字节[]kDate=HmacSha256(日期戳,以字节为单位(“AWS4”+键));
字节[]kRegion=HmacSha256(区域名称,kDate);
字节[]kService=HmacSha256(serviceName,kRegion);
返回HmacSha256(“aws4_请求”,k服务);
}
专用静态字节[]ToBytes(字符串str)
{
返回Encoding.UTF8.GetBytes(str.tocharray());
}
专用静态字符串HexEncode(字节[]字节)
{
返回BitConverter.ToString(字节)。替换(“-”,string.Empty)。ToLowerInvariant();
}
专用静态字节[]哈希(字节[]字节)
{
返回SHA256.Create().ComputeHash(字节);
}
专用静态字节[]HmacSha256(字符串数据,字节[]键)
{
返回新的HMACSHA256(键).ComputeHash(ToBytes(数据));
}
您是否愿意使用HttpClient
而不是WebRequest
?在这种情况下,我创建了一个名为的NuGet包,该包已被验证可与AWS API网关一起使用。基本上,我需要在amazon web serv中存储一个密钥值
public WebRequest RequestPost(string canonicalUri, string canonicalQueriString, string jsonString)
{
string hashedRequestPayload = CreateRequestPayload(jsonString);
string authorization = Sign(hashedRequestPayload, "PUT", canonicalUri, canonicalQueriString);
string requestDate = DateTime.ParseExact(DateTime.UtcNow.ToString(), "YYYYMMDD'T'HHMMSS'Z'", CultureInfo.InvariantCulture).ToString();
WebRequest webRequest = WebRequest.Create(canonicalUri + canonicalQueriString);
webRequest.Method = "PUT";
webRequest.ContentType = ContentType;
webRequest.Headers.Add("X-Amz-date", requestDate);
webRequest.Headers.Add("Authorization", authorization);
webRequest.Headers.Add("x-amz-content-sha256", hashedRequestPayload);
webRequest.ContentLength = jsonString.Length;
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] data = encoding.GetBytes(jsonString);
Stream newStream = webRequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
using (WebResponse response = webRequest.GetResponse())
{
StreamReader responseReader = new StreamReader(response.GetResponseStream());
var responseJson = responseReader.ReadToEnd();
}
return webRequest;
}
const string RegionName = "eu-west-1"; //This is the regionName
const string ServiceName = "execute-api";
const string Algorithm = "AWS4-HMAC-SHA256";
const string ContentType = "application/json";
const string Host = "<hostname>";
const string SignedHeaders = "content-type;host;x-amz-content-sha256;x-amz-date";
private static string CreateRequestPayload(string jsonString)
{
//Here should be JSON object of the model we are sending with POST request
//var jsonToSerialize = new { Data = String.Empty };
//We parse empty string to the serializer if we are makeing GET request
//string requestPayload = new JavaScriptSerializer().Serialize(jsonToSerialize);
string hashedRequestPayload = HexEncode(Hash(ToBytes(jsonString)));
return hashedRequestPayload;
}
private static string Sign(string hashedRequestPayload, string requestMethod, string canonicalUri, string canonicalQueryString)
{
var currentDateTime = DateTime.UtcNow;
var accessKey = "";
var secretKey = "";
var dateStamp = currentDateTime.ToString("yyyyMMdd");
//var requestDate = currentDateTime.ToString("YYYYMMDD'T'HHMMSS'Z");
var requestDate = DateTime.ParseExact(currentDateTime.ToString(), "YYYYMMDD'T'HHMMSS'Z'", CultureInfo.InvariantCulture);
var credentialScope = string.Format("{0}/{1}/{2}/aws4_request", dateStamp, RegionName, ServiceName);
var headers = new SortedDictionary<string, string> {
{ "content-type", ContentType },
{ "host", Host },
{ "x-amz-date", requestDate.ToString() }
};
string canonicalHeaders = string.Join("\n", headers.Select(x => x.Key.ToLowerInvariant() + ":" + x.Value.Trim())) + "\n";
// Task 1: Create a Canonical Request For Signature Version 4
string canonicalRequest = requestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + SignedHeaders + "\n" + hashedRequestPayload;
string hashedCanonicalRequest = HexEncode(Hash(ToBytes(canonicalRequest)));
// Task 2: Create a String to Sign for Signature Version 4
string stringToSign = Algorithm + "\n" + requestDate + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
// Task 3: Calculate the AWS Signature Version 4
byte[] signingKey = GetSignatureKey(secretKey, dateStamp, RegionName, ServiceName);
string signature = HexEncode(HmacSha256(stringToSign, signingKey));
// Task 4: Prepare a signed request
// Authorization: algorithm Credential=access key ID/credential scope, SignedHeadaers=SignedHeaders, Signature=signature
string authorization = string.Format("{0} Credential={1}/{2}/{3}/{4}/aws4_request, SignedHeaders={5}, Signature={6}",
Algorithm, accessKey, dateStamp, RegionName, ServiceName, SignedHeaders, signature);
return authorization;
}
private static byte[] GetSignatureKey(string key, string dateStamp, string regionName, string serviceName)
{
byte[] kDate = HmacSha256(dateStamp, ToBytes("AWS4" + key));
byte[] kRegion = HmacSha256(regionName, kDate);
byte[] kService = HmacSha256(serviceName, kRegion);
return HmacSha256("aws4_request", kService);
}
private static byte[] ToBytes(string str)
{
return Encoding.UTF8.GetBytes(str.ToCharArray());
}
private static string HexEncode(byte[] bytes)
{
return BitConverter.ToString(bytes).Replace("-", string.Empty).ToLowerInvariant();
}
private static byte[] Hash(byte[] bytes)
{
return SHA256.Create().ComputeHash(bytes);
}
private static byte[] HmacSha256(string data, byte[] key)
{
return new HMACSHA256(key).ComputeHash(ToBytes(data));
}