{
DateTime utcNow = DateTime.UtcNow;
var dataKey = GetKeyedHash(_configuration["YandexObjectStorage:SecretKey"],
utcNow.ToString("yyyyMMdd", CultureInfo.InvariantCulture));
var regionKey = GetKeyedHash(dataKey,"ru-central1");
var serviceKey = GetKeyedHash(regionKey,"s3");
var signinKey = GetKeyedHash(serviceKey,"aws4_request");
var preparedCanonicalRequest =Utils.ToHex(GetSha256(GetCanonicalRequest(fileName,utcNow,lifeTime)));
var stringForSign = String.Format(
"AWS4-HMAC-SHA256" + "\n" + "{0:yyyyMMddTHHmmssZ}" + "\n" + "{0}:yyyyMMdd" + "{1}" + "\n" + "{2}"
, utcNow, "/ru-central1/s3/aws4_request", preparedCanonicalRequest);
var signature = Utils.ToHex(GetKeyedHash( signinKey,stringForSign));
var str = $"{(object) "https://storage.yandexcloud.net"}"
+ "/" + $"{(object) _configuration["YandexObjectStorage:Bucket"]}" + "/"
+ $"{(object) fileName}" + "?"
+ "X-Amz-Algorithm="
+ $"{(object) "AWS4-HMAC-SHA256"}" + "&" +
"X-Amz-Credential=" + $"{(object) _configuration["YandexObjectStorage:AccessKey"]}" + "%2F" +
$"{utcNow:yyyyMMdd}" + "%2F" +
$"{(object) "ru-central1"}" + "%2F" +
$"{(object) "s3"}" + "%2F" +
$"{(object) "aws4_request"}" +
"&" + "X-Amz-Date=" +
$"{utcNow:yyyyMMddTHHmmssZ}" +
"&" + "X-Amz-Expires=" +
$"{(object) lifeTime}" + "&" + "X-Amz-Signature=" +
$"{(object) signature}" + "&" + "X-Amz-SignedHeaders=" +
$"{(object) "host"}";
return str;
}
private string GetCanonicalRequest(string fileName, DateTime utcNow, int expire)
{
var httpVerb = "GET";
var canonicalUrl = _configuration["YandexObjectStorage:Bucket"]+"/"+fileName;
var canonicalQueryString = String.Format("X-Amz-Algorithm=" +
"AWS4-HMAC-SHA256" +
"&X-Amz-Credential=" +
"{0}"+"%2F20190801%2Fru-central1%2Fs3%2Faws4_request" +
"&X-Amz-Date=" +
"{1:yyyyMMddTHHmmssZ}" +
"&X-Amz-Expires=" +
"{2}" +
"&X-Amz-SignedHeaders=" +
"host",_configuration["YandexObjectStorage:AccessKey"], utcNow, expire.ToString());
var canonicalHeaders = "host:storage.yandexcloud.net";
var signedHeaders = "host";
return httpVerb + "\n" +
canonicalUrl + "\n" +
canonicalQueryString + "\n" +
canonicalHeaders + "\n" +
signedHeaders + "\n" +
"UNSIGNED-PAYLOAD";
}
private byte[] GetSha256(string value)
{
HMACSHA256 hmacshA256 = new HMACSHA256();
hmacshA256.Initialize();
return hmacshA256.ComputeHash(Encoding.UTF8.GetBytes(value));
}
private byte[] GetKeyedHash(string key, string value) => GetKeyedHash(Encoding.UTF8.GetBytes(key), value);
private byte[] GetKeyedHash(byte[] key, string value)
{
HMACSHA256 hmacshA256 = new HMACSHA256(key);
hmacshA256.Initialize();
return hmacshA256.ComputeHash(Encoding.UTF8.GetBytes(value));
}
private static class Utils
{
private const string ValidUrlCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
public static string UrlEncode(string data)
{
Код не стоит кидать сюда портянками. Для этого есть гораздо более удобные инструменты. Например https://gist.github.com
Почему не возьмете SDK просто?
в SDK нет метода получения подписанной ссылки)
А это что? https://docs.aws.amazon.com/AmazonS3/latest/userguide/example_s3_Scenario_PresignedUrl_section.html
Обсуждают сегодня