【问题标题】:Update Google AMP cache URL signature verification error更新 Google AMP 缓存 URL 签名验证错误
【发布时间】:2018-09-16 11:48:09
【问题描述】:

我正在尝试在 Google AMP 缓存中更新我的 Google AMP 页面,但收到 URL 签名验证错误。

我的代码:

Dim tStamp As String = GetUnixTimeStampFromDateTime(DateTime.Now).ToString
Dim ampBaseUrl As String = "https://www-example-com.cdn.ampproject.org"
Dim signatureUrl As String = "/update-cache/c/s/www.example.com/articles/278/myarticle/amp?amp_action=flush&amp_ts=" + tStamp

Dim rsa As RSA = certificate.GetRSAPrivateKey()
Dim data() As Byte = System.Text.Encoding.Unicode.GetBytes(signatureUrl)
Dim sig() As Byte = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)

Dim AMPURLSignature As String = EncodeTo64(sig.ToString)

编码函数:

Public Shared Function EncodeTo64(ByVal toEncode As String) As String
    Dim toEncodeAsBytes As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode)
    Dim returnValue As String = System.Convert.ToBase64String(toEncodeAsBytes)
    Return returnValue
End Function

我尝试使用 this URL 调用 Google AMP 缓存。

现在,我收到 403 错误:

您的客户无权获取网址 /update-cache/c/s/www.example.com/articles/278/myarticle/amp?amp_action=flush&amp_ts=1523016476&amp_url_signature=U2lzdGVtLkJ5dGVbdQ。 URL 签名验证错误。这就是我们所知道的。

我发现谷歌示例代码不够清晰:https://developers.google.com/amp/cache/update-cache

我的问题是关于签名 URL:

  1. 我是使用文章 AMP URL 还是常规 URL?
  2. 是否需要在我的签名 URL 中包含查询字符串参数 amp_actionamp_ts?还是在我签署 URL 之后再附加这些?
  3. 我应该将上面的 ampBaseUrl 添加到我的 signatureUrl 变量之前,还是不需要这样做?

更新 1

根据@CodeFuller 的建议,我检查了网址并收到了Verified OK 消息。我还处理了第 2 步:

  1. APIkeys 匹配:https://www.toptrouwen.nl/.well-known/amphtml/apikey.pub 匹配 https://www-toptrouwen-nl.cdn.ampproject.org/r/s/www.toptrouwen.nl/.well-known/amphtml/apikey.pub
  2. 从我的服务器提供 apikey.pub 作为文本/纯文本
  3. 通过 https 公开提供 apikey.pub
  4. 在机器人中添加了不允许:用户代理:* 禁止:/.well-known/amphtml/apikey.pub

更新 2

是的,使用新代码,我还会在验证时获得Verified OK

生成此网址: https://www-toptrouwen-nl.cdn.ampproject.org/update-cache/c/s/www.toptrouwen.nl/artikelen/132/het-uitwisselen-van-de-trouwringen-hoe-voorkom-je-bloopers/amp?amp_action=flush&_ts=1523138180&_url_signature=tKPO3k624ybwxoEynqN8oI3/UDxhq1TF8jX9aKeVyL0IWLUODXuMB7ansP0t1+/5Lm2V7RYZbUWxt2Whh7+LFEmfQFGJJE/iPtoBVsqrdb5356QwiIrDHOzY+3z5dASZxYlAwlfzUFdonGyDsh/UlCjjvvNahFEWzHOpB5JQxJQ1Wn0kGLQUF1v2u47abbae6cNQBm3YB/0Z1FLfTJLM1oOEOSDh9vQH1SqO/6SoYtUhSQjSrYdl/g5O0QJ7A9pKUxOPfgVJM0l8Sgb66cVeWWoWq0WIFe24RPXUMl9tIFFZ1TY2R+ZpIMvpEAPDjCsdGPo7KTWqGb4qfoTBINJmtQ==

然后我收到错误 Required query parameter 'amp_url_signature' missing.(与之前的问题有关,amp_ 参数被搞砸了。

然后我将 URL 参数重命名为正确的名称:https://www-toptrouwen-nl.cdn.ampproject.org/update-cache/c/s/www.toptrouwen.nl/artikelen/132/het-uitwisselen-van-de-trouwringen-hoe-voorkom-je-bloopers/amp?amp_action=flush&amp_ts=1523138180&amp_url_signature=tKPO3k624ybwxoEynqN8oI3/UDxhq1TF8jX9aKeVyL0IWLUODXuMB7ansP0t1+/5Lm2V7RYZbUWxt2Whh7+LFEmfQFGJJE/iPtoBVsqrdb5356QwiIrDHOzY+3z5dASZxYlAwlfzUFdonGyDsh/UlCjjvvNahFEWzHOpB5JQxJQ1Wn0kGLQUF1v2u47abbae6cNQBm3YB/0Z1FLfTJLM1oOEOSDh9vQH1SqO/6SoYtUhSQjSrYdl/g5O0QJ7A9pKUxOPfgVJM0l8Sgb66cVeWWoWq0WIFe24RPXUMl9tIFFZ1TY2R+ZpIMvpEAPDjCsdGPo7KTWqGb4qfoTBINJmtQ==

然后我得到:404 Failed to decode amp_url_signature,我认为这是因为 URL 中有 +\ 字符。当我删除它们时,我再次收到错误URL signature verification error

我认为 UTC 时间戳目前不是问题,因为我之前已经看到如果时间戳不正确,Google 会抛出错误。

【问题讨论】:

  • 您可以尝试发布您的问题here,这是他们的问题跟踪器中有关更新缓存的帖子。您也可以尝试在How to Update Google AMP Cache 上查看本指南。希望这会有所帮助。

标签: amp-html


【解决方案1】:

URL signature verification error 有两个最常见的原因:

  1. 签名计算不正确。

    所以首先要验证签名是否确实有效。将签名的 URL 和结果签名保存到一些文件中:

    Dim signatureUrl As String = "/update-cache/c/s/www.example.com/articles/278/myarticle/amp?amp_action=flush&amp_ts=" + tStamp
    ' ...
    Dim sig() As Byte = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)
    File.WriteAllText("url.txt", signatureUrl)
    File.WriteAllBytes("signature.bin", sig)
    

    然后用openssl工具验证签名:

    openssl.exe dgst -sha256 -signature signature.bin -verify publickey.pem url.txt

    如果输出是

    验证正常

    那么你的签名没问题,你应该在其他地方搜索问题(参见第 2 项)。

    如果输出是

    验证失败

    那么你应该重新检查签名计算的例程。

    上面命令中的publickey.pem是PEM格式的公钥。它应该以以下行开头:

    -----BEGIN PUBLIC KEY-----

    如果您有证书文件(以-----BEGIN CERTIFICATE----- 开头),您可以使用以下命令为它get PEM

    openssl.exe x509 -pubkey -noout -in publickey.cer > publickey.pem

  2. 如果签名验证成功,那么您应该检查您的公钥是否可以通过 Web 访问。 Update AMP Content 声明以下要求:

    对于签名验证,您必须在 AMP 文档域的固定位置提供公共 RSA 密钥(要生成密钥,请参阅生成 RSA 密钥)。例如:

    https://example.com/.well-known/amphtml/apikey.pub

    • 公钥不能被机械化。

    • URL 必须是 HTTPS。

    • 域必须是您要更新的确切域,而不是子域或超级域。

    • 您必须以 PEM 格式发布密钥并使用内容类型“text/plain”提供密钥。

    因此,如果您的 AMP 基本 URL 是 https://www.test.com,请检查您的公钥是否可以通过以下 URL 访问:https://www.test.com/.well-known/amphtml/apikey.pub

以下是您其他问题的答案:

我是否需要在我的签名 URL 中包含查询字符串参数 amp_action 和 amp_ts?还是在我签署 URL 之后再附加这些?

是的,您应该在计算签名的 URL 中包含 amp_actionamp_ts

我应该将上面的 ampBaseUrl 添加到我的 signatureUrl 变量中还是不需要?

Update AMP Content文章所述:

AMP 缓存主机名 (cdn.ampproject.org) 被排除在 签名以允许向多个 AMP 提交相同的签名请求 缓存操作符。

因此,您不应在计算签名的 URL 中包含 ampBaseUrl

更新

我在将签名附加到 URL 的代码中发现了另一个错误:

Dim AMPURLSignature As String = EncodeTo64(sig.ToString)

sig.ToString 将导致将"System.Byte[]" 字符串传递给EncodeTo64,而不是实际的签名字节。结果附加了不正确的签名以更新缓存 URL。将上述调用替换为以下内容(不再需要EncodeTo64):

Dim AMPURLSignature As String = System.Convert.ToBase64String(sig)

另一个可能的问题是你使用的时间戳不满足following requirement

该值应该是当前时间,以秒为单位,必须在 在当前时间之前或之后 1 分钟

您将DateTime.Now 传递给GetUnixTimeStampFromDateTime(),但它应该是UTC 时间,而不是本地时间。尝试将tStamp 计算替换为:

Dim tStamp As String = CInt((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds).ToString

还要确保在生成update-cache URL 后立即调用它,以便与时间戳相比,当前时间在 1 分钟间隔内。而且你的系统时间应该是精确的。

以上修复后请重新检查签名验证是否通过。

更新 2(关于签名中的 +/ 字符)

AMP 缓存更新签名 should go 在 base4 编码的变体中:

使用web-safe variant of base64对二进制RSA签名进行编码

因此,另一个需要的解决方法是将 +/ 字符替换为 -_

更改后续调用

Dim AMPURLSignature As String = System.Convert.ToBase64String(sig)

与:

Dim AMPURLSignature As String = ToWebSafeBase64(sig)

' ...

Private Function ToWebSafeBase64([data]() As Byte) As String
    Dim base64 = System.Convert.ToBase64String(data)
    base64 = base64.Replace("+", "-")
    base64 = base64.Replace("/", "_")
    Return base64
End Function

更新 3

这是应该产生正确的update-cache URL(基于available documentation)的最终代码:

Module MainModule

    Sub Main()

        Dim tStamp As String = CInt((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds).ToString
        Dim ampBaseUrl = "https://www-toptrouwen-nl.cdn.ampproject.org"
        Dim signatureUrl As String = "/update-cache/c/s/www.toptrouwen.nl/artikelen/132/het-uitwisselen-van-de-trouwringen-hoe-voorkom-je-bloopers?amp_action=flush&amp_ts=" + tStamp

        Dim data() As Byte = System.Text.Encoding.ASCII.GetBytes(signatureUrl)

        Dim certificate = New X509Certificate2("d:\temp\keys\keys.pfx", "12345")
        Dim rsa As RSA = certificate.GetRSAPrivateKey()
        Dim sig() As Byte = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)

        Dim ampUrlSignature As String = ToWebSafeBase64(sig)
        Dim url As String = ampBaseUrl + signatureUrl + "&amp_url_signature=" + ampUrlSignature

        Console.WriteLine(url)

    End Sub

    Private Function ToWebSafeBase64([data]() As Byte) As String
        Dim base64 = System.Convert.ToBase64String(data)
        base64 = base64.Replace("+", "-")
        base64 = base64.Replace("/", "_")
        Return base64
    End Function

End Module

Sample Project on GitHub

它产生以下网址:

https://www-toptrouwen-nl.cdn.ampproject.org/update-cache/c/s/www.toptrouwen.nl/artikelen/132/het-uitwisselen-van-de-trouwringen-hoe-voorkom-je-bloopers?amp_action=flush&amp_ts=1523188941&amp_url_signature=bZJTE4IjlxGhlU79etivzUPpGFoyKvCxqPO1IOPHfzDKQVt-fA8Mte20SeXjTQs24Uy4RD9lmbS2aXlcCTpOYatF2l8PQ-31kR-lKVnuduSZIrg93g2YrvO7x-a6dr19hN74LywgBw4C_JfuocCuGfVvr-mD40tuwkBrsLgmI9E=

此签名已使用 opensll 工具成功验证,但获取此 URL 仍返回 URL signature verification error.。然而,现在一切似乎都在我们这边。我找到了related issue on github。有以下statement from AMP project contributor:

首先,我确定 AMP Cache 不处理 HTTP 刷新 正确更新缓存验证密钥:如果您发出 更新缓存请求,然后交换 /.well-known/amphtml/apikey.pub 使用不同的密钥,我们会无限期地继续使用旧的密钥材料。 更糟糕的是,404 响应也会被永久缓存:-(

我提交了一份内部错误报告,但可能需要一些时间 修复以推出生产。同时,我可以刷新无效键 手动。只需在 GitHub 或上给我发私信 amphtml.slack.com。很抱歉没有早点发现这一点。

似乎这是当前错误的根本原因。当https://www.toptrouwen.nl/.well-known/amphtml/apikey.pub 没有可用的公钥时,您尝试更新缓存(当我第一次检查它时,它导致了 404 错误)。 Google 已经缓存了这个结果,现在即使证书可用,它也没有实际使用。

目前看来唯一可能的解决方法是联系 codewiz 并要求他刷新缓存的密钥错误。在 AMP 系统使用有效公钥之前,无法进行签名验证。

【讨论】:

  • 我添加了更新 1,所以一切看起来都井井有条。难道我的 ASP.NET 代码输出的 URL 与 url.txt 文档中的 URL 不同吗? url.txt 包含正确的 URL,但我的 ASP.NET 打印到网站忽略了查询字符串参数中的 amp...请参阅此问题中的更新 3:stackoverflow.com/questions/49477892/…
  • 请根据您的新代码检查我添加的更新 2
  • 拿到带有签名的URL后,如何发送HTTP GET呢? &amp 不应从 URL 中消失,除非您将其粘贴到某个 HTML 页面。请参阅我关于签名中+/ 字符的答案的更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-09
  • 2023-04-01
  • 2021-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多