到期时间用于限制授权的生命周期,以由拥有签名 URL 的任何人执行允许的操作。
当然,如果不使签名无效,就无法更改 URL 中的过期时间,因为它是 HMAC 的输入之一,但过期时间本身对签名算法的实际安全性没有任何贡献,因为:
即使它确实向被散列的消息添加信息,它也不会添加任何秘密信息
如果我们假设暴力破解在计算上是可行的,那么 URL 已“过期”这一事实并不能阻止恶意行为者暴力破解它……因为您不需要 S3 来确认您已经暴力破解了我的签名秘密. 当您的签名算法根据相同的输入产生与我相同的输出时,您就赢了。当然,您拥有的特定URL 现在已过期,但现在您有了我的签名秘密,并且可以在您喜欢的任何过期时间签署任何您喜欢的 URL。
请注意,我在这里所说的任何内容都不应被视为暗示我认为签名算法的安全性存在缺陷——我唯一的观点是,如果到期时间,到期时间不会影响算法将提供的任何安全级别不是一个组件。
同样为了清楚起见,由于过期时间是签名消息的一部分,因此根据定义,过期时间是防篡改的。昨天过期的我的有效 URL 不能调整为“明天过期”并且其签名仍然有效。
您提到的 Signature Version 2 算法非常简单。从概念上讲,您将要发出的请求规范化,然后通过 HMAC 运行它。 请求中涉及的任何内容都不是秘密的,除了密钥。请求本身(HMAC 函数的输入消息),包括过期时间,没有隐藏组件。它不能,因为那时 S3 将无法生成相同的签名,因为我没有关于即将到来的请求的秘密通信——这就是签名算法的工作方式——对于任何给定的请求(HTTP 动词、内容-MD5 标头值(如果要发送),Content-Type 标头值(如果要发送),过期时间,规范化X-Amz
标头(如果要发送),最后/${bucket}/${key}{$canonical_query_string}
, 所有这些元素在它们之间连接在一起\n
。
S3 知道我的秘密(事实上,显然所有 AWS 服务都知道,因此它们可以验证我的请求),并尝试生成与我相同的签名。如果成功,则如果其凭据签署请求的用户实际上被允许发出请求,则该请求被允许。
如果您拥有我生成的签名 URL,则可以通过复制我将签名的消息(您已经知道所需的一切,从 URL 中执行此操作)来蛮力进行,并且在你计算的和Signature
我在我签名的 URL 中给你的一样,你已经破解了我的密钥。对于任何给定的请求和到期时间,只能有一个正确的签名。
当然,祝那个破解项目好运,因为我会在几周或几个月后将我的密钥(及其随附的秘密)转出活动状态并禁用它,早在你有一个有意义的机会破解它之前。
但关键是,就像进入我正在 HMAC 的消息中的所有其他组件一样,您&Expires=
在 URL 中看到,并且您知道那里的值是什么,以便重现我签名的原始消息。过期不会使您的任务复杂化。
不,过期是严格控制我分发的签名 URL 的有效生命周期,理论上未经授权访问该 URL 需要一段时间才能发生。信息越敏感,一般来说,您应该将请求过期时间设置为越短。
旁注:包含过期时间也给后端服务器一个小的优化,你可以自己证明——首先检查过期时间, 在检查签名的有效性之前。毕竟,没有必要花费 CPU 周期来尝试验证伴随着过期时间的签名,该过期时间清楚地表明它已经过期。S3 似乎通过在过期时间过去时返回相同的“请求已过期”错误来缩短这项不必要的工作,而不考虑签名是否有效。您可以通过手动更改有效请求的到期时间来确认这一点。如果您将其设置为过去,这会使签名无效,但您得到的错误是“请求已过期”。如果将其设置为将来,这也会使签名无效,但您收到的错误表明签名无效。
另外:签名版本 4 比 V2 更复杂——甚至更安全——算法,使用 HMAC-SHA256 的 5 次嵌套迭代......并且没有 5 次迭代,因为“越多越好”的错误观念。”
事实上,我花了一段时间才理解这个算法设计的含义,这似乎是一个相当出色的算法。
如果您剥离这些层,很明显 AWS 已设计此算法以在内部(即在 AWS 内部)根据最小特权原则委托信任。
最里面的 HMAC 迭代是由今天的日期组成的消息,使用由字符串“AWS4”+ my secret 组成的秘密签名。那是日期键。它只适用于 7 天。IAM 的中央安全存储库是唯一知道我的秘密和我的 DateKey 的实体。
下一次迭代使用 DateKey 的输出对 AWS 区域的文字名称(例如us-west-2
)进行签名,以派生 DateRegionKey。然后 IAM 可以将此值传递给每个区域内的子系统,这样他们就知道他们需要知道的所有信息,以便验证我在他们所在区域的签名,但不是在全球范围内。
接下来,s3
使用 DateRegionKey对 AWS 服务名称(例如)进行签名,以生成 DateRegionServiceKey。对于每个区域,IAM 子系统可以为每个服务生成此密钥,向每个服务提供该服务需要知道的所有信息,以便在该区域内验证我的服务签名 - 并且(再次)仅此而已。
然后,使用 DateRegionServiceKey 对字符串“aws4_request”进行签名,形成我的日常签名密钥。由于“aws4_request”本质上只是一个字符串,因此每个服务都可以派生(而不是存储)我今天将用来签署请求的签名密钥,因此只有它需要的信息,仅此而已。
最后,我的日常签名密钥用于签署每个规范化的请求。
你看到他们在那儿做了什么吗?
除了 IAM 核心系统之外,没有任何系统需要知道我的实际秘密。例如,如果 S3 区域的基础设施存在内部漏洞(尽管不太可能),攻击者可以获得的信息不会向他们透露我的实际秘密——只有该区域中的 S3 知道的秘密。如果区域基础设施遭到破坏,则在其他区域等中获得的凭据将毫无用处,直到链上的根。
V4 算法似乎是一个安全的、全球分布的、秘密的签名密钥委托系统的核心,在这个系统中,内部的一切都是需要知道的。就像我说的……它看起来相当出色。