AWSS3 iOS 认证方法-V4认证
身份验证方法
HTTP验证头
使用HTTP验证请求头是最普遍的验证请求方法.
查询字符串参数
可以在URL中使用一个查询字符串来表示验证请求. 这种情况下,可以使用查询参数来请求信息,包括验证信息.
由于请求签名是URL中的一部分,URL的类型经常被认为是一个预签名的URL.可以在HTML中使用预签名的URL嵌入可点击的链接,有效期长达7天.
签名请求介绍
请求中的验证信息包括一个签名. 为了计算签名,
首先,计算选择请求元素来生成一个字符串,简称签名字符串.
其次,使用签名密钥来计算签名串的基于哈希散列的验证码.
在V4验证中,不使用AK和SK来签名请求,使用AK和SK创建签名密钥. 签名密钥的作用范围是一个特定的区域和服务,它用不过期.
计算签名过程
StringToSign
:
A string based on select request elements.
Signing Key
DateKey = HMAC-SHA256("AWS4" + "<SecretAccessKey>","<yyyymmdd>")
DateRegionKey = HMAC-SHA256(DateKey,"<aws-region>")
DateRegionServiceKey = HMAC-SHA256(DateRegionKey,"<aws-service>")
SigningKey = HMAC-SHA256(DateRegionServiceKey, "aws4_request")
- Signature
signature = Hex(HMAC-SHA256(SigningKey, StringToSign))
签名字符串依赖请求类型.例如,当使用HTTP验证请求头或查询字符串参数验证签名的,
使用不同的请求元素组合来创建签名字符串.
对于一个HTTP POST请求,请求中的POST的策略就是签名字符串. 一旦收到验证消息,服务器使用请求中包含的验证信息来创建签名.
如果签名匹配,请求验证通过,否则请求被拒绝.
签名计算根据选择传送文件的选项变化而变化.
目前支持传送单块和传送多块选项.
传送单块
包括有符号的文件选项和无符号的文件选项.
有符号的文件选项计算整个文件的校验并在签名中包括它.
这提供了额外的安全性,但是需要读取文件两次或在内存中缓冲它.
例如,为了上传一个文件,首次读取文件是为了签名计算一个文件哈希,再次读取文件是创建请求时的传输.
对于小文件这样是可以接受的,但是对于大文件,读取两次文件不是高效的,因此上传多个块来支持这种情况.
无符号的文件选项不包括签名计算中的文件校验.
认可的规范行为:
Canonical Request
HTTP Verb + “\n” +
Canonical URI + “\n” +
Canonical Query String + “\n” +
Canonical Headers + “\n” +
Signed Headers + “\n” +
Hashed PayloadStringToSign
“AWS4-HMAC-SHA256” + “\n” +
TimeStamp + “\n” +
Scope + “\n” +
Hex(SHA256Hash(Canonical Request
))
Signing Key:
DateKey = HMAC-SHA256(“AWS4” + “”,“”)
DateRegionKey = HMAC-SHA256(DateKey,“”)
DateRegionServiceKey = HMAC-SHA256(DateRegionKey,“”)
SigningKey = HMAC-SHA256(DateRegionServiceKey, “aws4_request”)
Signature = Hex(HMAC-SHA256(SigningKey, StringToSign))
以上:
Canonical Request
说明:
HTTP Verb
: “GET / PUT / POST /…”,
Canonical URI
: UriEncode(resource),
Canonical Query String
:
UriEncode(QueryParametert1)+ “=” + UriEncode(value) + “&” +
…
UriEncode(QueryParameterN) + “=” + UriEncode(value)
(Sorted by QueryParamete)
Canonical Headers
:
Lowercase(HeaderName1) + “:” + Trim(value) + “\n”
…+
Lowercase(HeaderNameN) + “:” + Trim(value) + “\n”
(Sorted by HeaderName)
Signed Headers
:
Lowercase(HeaderName1) + “;” +
Lowercase(HeaderName2) + “;” +
… +
Lowercase (HeaderNameN)
(Sorted by HeaderName)
Hashed Payload
: (Hex(SHA256Hash(payload))
StringToSign
说明:
TimeStamp
: Format IS08601, e.g. “20130524T000000Z”
Scope
: “yyyymmdd/AWS Region/s3/aws4_request” e.g.,“20130524/us-east-1/s3/aws4 request”
传送多块
采用多块传输文件不考虑文件的大小.
将文件分成多块,可以是固定的或可变大小的块.
通过多块上传,避免了读取整个文件来计算签名,取而代之的是对于第一块,仅仅使用请求头计算种子签名.
第二块保存第一块的签名,后续的块保存上一个块的签名.
在上传结束时,发送一个0字节数据的包括了最后一个块的签名的完成块.
计算种子签名的原理:
1. Canonical Request
HTTP Verb + “\n” +
Canonical URI + “\n” +
Canonical Query String + “\n” +
Canonical Headers + “\n” +
Signed Headers + “\n” +
“UNSIGNED-PAYLOAD”
2. StringToSign
“AWS4-HMAC-SHA256” + “\n” +
TimeStamp + “\n” +
Scope + “\n” +
Hex(SHA256Hash(Canonical Request))
3. Signature
Signing Key
:
DateKey = HMAC-SHA256(“AWS4” + “SecretAccessKey”,“yyyymmdd”)
DateRegionKey = HMAC-SHA256(DateKey,“aws-region”)
DateRegionServiceKey = HMAC-SHA256(DateRegionKey,“aws-service”)
SigningKey = HMAC-SHA256(DateRegionServiceKey, “aws4_request”)
Signature
= Hex(HMAC-SHA256(SigningKey, StringToSign))
以上:
Canonical Request说明:
HTTP Verb
: “GET / PUT / POST /…”
Canonical URI
: UriEncode(resource)
Canonical Query String
:
UriEncode(QueryParametert1)+ “=” + UriEncode(value) + “&” +
…
UriEncode(QueryParameterN) + “=” + UriEncode(value)
(Sorted by QueryParamete)
Canonical Headers
:
Lowercase(HeaderName1) + “:” + Trim(value) + “\n”
…+
Lowercase(HeaderNameN) + “:” + Trim(value) + “\n”
(Sorted by HeaderName)
Signed Headers
:
Lowercase(HeaderName1) + “;” +
Lowercase(HeaderName2) + “;” +
… +
Lowercase (HeaderNameN)
(Sorted by HeaderName)
StringToSign说明:
TimeStamp
: Format IS08601, e.g. “20130524T000000Z”
Scope
: “yyyymmdd/AWS Region/s3/aws4_request”
e.g. “20130524/us-east-1/s3/aws4 request”
在发送请求时,在x-amz-content-sha256
头中必须指明选择了哪种签名计算方式,包括以下中的一种:
. 选择多块上传 x-amz-content-sha256
值为STREAMING-AWS4-HMAC-SHA256-PAYLOAD
. 选择单块上传 x-amz-content-sha256
值为检验值,或者该值为UNSIGNED-PAYLOAD
验证请求头
使用验证消息头是最普遍的提供验证信息的方法.除了post请求和使用查询参数签名的请求外,
所有bucket操作和object操作都是使用验证请求头来提供验证信息的.
举例:
Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,
SignedHeaders=host;range;x-amz-date,
Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
说明:
AWS4-HMAC-SHA256
: 计算签名的算法,使用V4签名验证必须提供该值。
Credential: 访问密钥标识和范围信息。包括日期,区域和用来计算签名的服务。
该字段格式如下:your-access-key-id/date/aws-region/aws-service/aws4_request
其中:date
该值使用YYYYMMDD
格式。aws-service
该值是s3
。
SignedHeaders
: 用于计算签名的分号分隔的请求标头列表。这个列表仅包括头名称(必须小写)。
Signature
: 16进制小写字符表示的256位签名。
例如: fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
使用查询参数
当你想在一个URL中表达一个请求时,使用查询参数来验证请求时非常有用的.这种方法也被称为预签名URL.
一个预签名URL使用的情况是,你可以给你的资源临时访问权限.
例如,可以在网站中嵌入一个预签名URL或者在客户端使用这个URL来下载object
举例:
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>
说明:
换行是为了提升可读性。
URL中的x-amz-credential
值显示“/”字符是为了可读性。实际中应该编码为%2F
。
例如: &X-Amz-Credential=<your-access-key-id>%2F20130721%2Fus-east-1%2Fs3%2Faws4_request
字段说明:
X-Amz-Algorithm
: 标识签名版本和计算签名的算法。
X-Amz-Credential
: 访问密钥标识和范围信息。包括日期,区域和用来计算签名的服务。
该字段格式如下:your-access-key-id
/date
/aws-region
/aws-service
/aws4_request 其中:date
该值使用YYYYMMDD
格式。aws-service
该值是s3
。
X-Amz-Date
: 日期和时间格式必须遵守ISO 8601
标准。采用格式为yyyyMMddTHHmmssZ
。
X-Amz-Expires
: URL的有效期,以秒形式表示。
X-Amz-SignedHeaders
: 列出用于计算签名的头文件。签名计算中需要HTTP的host头和任何添加到请求中的x-amz-
头。
为了安全起见,请将所有签名计算需要的头信息放入请求中。
X-Amz-Signature
: 提供签名来验证请求。
计算签名:
Canonical Request
HTTP Verb + “\n” +
Canonical URI + “\n” +
Canonical Query String + “\n” +
Canonical Headers + “\n” +
Signed Headers + “\n” +
“UNSIGNED-PAYLOAD”StringToSign
“AWS4-HMAC-SHA256” + “\n” +
TimeStamp + “\n” +
Scope + “\n” +
Hex(SHA256Hash(Canonical Request))- Signature
Signing Key
:
DateKey = HMAC-SHA256(“AWS4” + “SecretAccessKey”,“yyyymmdd”)
DateRegionKey = HMAC-SHA256(DateKey,“aws-region”)
DateRegionServiceKey = HMAC-SHA256(DateRegionKey,“aws-service”)
SigningKey = HMAC-SHA256(DateRegionServiceKey, “aws4_request”)
Signature
= Hex(HMAC-SHA256(SigningKey, StringToSign))
以上:
Canonical Request说明:
HTTP Verb
: “GET / PUT / POST /…”
Canonical URI
: UriEncode()
Canonical Query String
:
UriEncode(QueryParametert1)+ “=” + UriEncode(value) + “&” +
…+
UriEncode(QueryParameterN) + “=” + UriEncode(value)
(Sorted by QueryParamete)
Canonical Headers
:
Lowercase(HeaderName1) + “:” + Trim(value) + “\n”
…
Lowercase(HeaderNameN) + “:” + Trim(value) + “\n”
(Sorted by HeaderName)
Signed Headers
:
Lowercase(HeaderName1) + “;” +
Lowercase(HeaderName2) + “;” +
… +
Lowercase (HeaderNameN)
(Sorted by HeaderName)
StringToSign说明:
TimeStamp
: Format IS08601, e.g. “20130524T000000Z”
Scope
: “yyyymmdd/AWS Region/s3/aws4_request”
e.g. “20130524/us-east-1/s3/aws4 request”