【发布时间】:2019-02-05 14:16:47
【问题描述】:
在 C# 中是否有任何示例可以查看如何使用带有 AWS v4 signature 的起始策略对所有对象进行预签名,以让客户从各自的文件夹结构中下载对象,而不是分别对每个文档进行签名。
文档说:
https://s3.amazonaws.com/examplebucket/test.txt
?X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=<your-access-key-id>/20130721/us-east-1/s3/aws4_request
&X-Amz-Date=20130721T201207Z
&X-Amz-Expires=86400
&X-Amz-SignedHeaders=host
&X-Amz-Signature=<signature-value>
但我的签名不适用于 GET(下载)对象,在上传时正常工作
void Main()
{
string bucket = "bucket-name-here";
string s3Key = "s3-key-here";
string s3Secret = "secret-here";
string s3Region = "us-east-1";
string Date = DateTime.UtcNow.ToString("yyyyMMdd");
string xAmzDate = DateTime.UtcNow.ToString("yyyyMMdd") + "T000000Z";
string expiration = DateTime.UtcNow.AddDays(1).ToString("yyyy-MM-ddTHH:mm:ssK");
string policyString = $@"{{""expiration"":""{expiration}"",""conditions"":[{{""bucket"":""{bucket}""}},{{""acl"":""private""}},[""starts-with"",""$key"",""Client_1""],[""starts-with"",""$Content-Type"",""""],[""starts-with"",""$filename"",""""],{{""x-amz-date"":""{xAmzDate}""}},{{""x-amz-credential"":""{s3Key}/{Date}/us-east-1/s3/aws4_request""}},{{""x-amz-algorithm"":""AWS4-HMAC-SHA256""}}]}}";
var policyStringBytes = Encoding.UTF8.GetBytes(policyString);
var policy = Convert.ToBase64String(policyStringBytes);
//policy.Dump();
byte[] signingKey = GetSigningKey(s3Secret, Date, s3Region, "s3");
byte[] signature = HmacSHA256(policy, signingKey);
var sign = ToHexString(signature);
sign.Dump();
}
static byte[] HmacSHA256(String data, byte[] key)
{
String algorithm = "HmacSHA256";
KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}
private byte[] GetSigningKey(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;
}
public static string ToHexString(byte[] data)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sb.Append(data[i].ToString("x2", CultureInfo.InvariantCulture));
}
return sb.ToString();
}
有关问题的更多信息:我们在 S3 上为数百个客户提供了数千个文档,它们各自的文件夹结构如下所示。现在,每次客户想要下载他们的对象时,他们都会被我们的 API 签名以创建可下载链接 > 因此每个文档都是单独签名的。
客户端 1
Client_1/Document1.xyz
Client_1/Document2.xyz
客户端 2
Client_2/Document1.xyz
Client_2/Document2.xyz
【问题讨论】:
-
与您的问题无关,请注意您的上传策略存在安全漏洞。
[""starts-with"",""$key"",""Client_1""]应该是[""starts-with"",""$key"",""Client_1/""],否则对于标识符是另一个客户端的左锚定子字符串的任何客户端,Client_1 可以覆盖 Client_10、Client_11 等文件,因为您没有在策略中放置终止分隔符语句对对象键的约束。此策略在浏览器中可见,因此恶意用户可以轻松找到并利用此策略。 -
非常感谢@Michael-sqlbot。我接受您的漏洞,虽然它在浏览器上不可见,并且浏览器看到我们 API 的散列策略 + 签名,并且这些散列值用于 put 请求的 s3 请求标头中。请注意我的代码中的 Convert.ToBase64String(policyStringBytes)。但无论如何,很棒的收获,真的很感激。对实际问题有什么建议吗?
-
出于所有实际目的,策略内容仍然是“可见的”,即使眼球实际上不可见,因为 base64 不是散列算法。解码很简单。
标签: c# amazon-web-services amazon-s3