【发布时间】:2018-09-03 19:07:37
【问题描述】:
我想更新 Google AMP 缓存,因此我需要按照here 的说明对 URL 进行签名。
我的主要问题:我正在为如何获取证书/密钥以及如何将它们包含在下面的代码中而苦苦挣扎。 我只是找不到任何适用于 Windows 和 IIS 的全部说明。
我一直在阅读这些帖子:
- Using /update-cache requests to update AMP pages
- How can I sign a file using RSA and SHA256 with .NET?
我不想使用我的计算机的证书存储,如第二篇文章中所述。我宁愿将磁盘上的文件用于公钥和私钥。
从我的生产服务器 IIS 中,我将我的证书导出到一个 .pfx 文件,然后使用this site 底部的说明从中提取私钥和证书。
server.key 包含-----BEGIN RSA PRIVATE KEY-----,如果我使用它加载到下面代码中的privateCert 变量中,则会抛出错误Cannot find the requested object.
我从 SSL 提供商那里得到的信息:
www_example_com.crt、www_example_com.p7b、certificate code(见下文)。
我已采取的步骤:
- 我通过打开
www_example.com.crt并使用Copy to file向导将其复制到base64 编码的.cer 文件来创建test-public-key.cer。 - 我保存了从 SSL 提供商处收到的
certificate code文件test-private-key.cer。
当我运行以下代码时出现错误
对象引用未设置为对象的实例。
在线key.FromXmlString(privateCert.PrivateKey.ToXmlString(True))
Dim publicCert As X509Certificate2 = New X509Certificate2("C:\temp\_certificates\test-public-key.cer")
Dim privateCert As X509Certificate2 = New X509Certificate2("C:\temp\_certificates\test-private-key.cer")
'Round-trip the key to XML and back, there might be a better way but this works
Dim key As RSACryptoServiceProvider = New RSACryptoServiceProvider
key.FromXmlString(privateCert.PrivateKey.ToXmlString(True))
'Create some data to sign
Dim data() As Byte = System.Text.Encoding.Unicode.GetBytes(signatureUrl)
'Sign the data
Dim sig() As Byte = key.SignData(data, CryptoConfig.MapNameToOID("SHA256"))
Dim AMPURLSignature As String = EncodeTo64(sig.ToString)
'Lastly, the verification can be done directly with the certificate's public key without need for the reconstruction as we did with the private key:
key = CType(publicCert.PublicKey.Key, RSACryptoServiceProvider)
If Not key.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), sig) Then
Throw New CryptographicException
End If
EncodeTo64 函数
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
certificate code
-----开始证书-----
MIIF (...) DXuJ
-----结束证书-----
更新 1
按照this page 上的导出步骤,我能够生成一个 mysite.pfx 文件。 在向导中,我确保选择“是,导出私钥”并添加了密码。其余步骤我逐字执行。
然后我还运行了这些命令:openssl pkcs12 -in mysite.pfx -nocerts -out private-key-VPS.pempenssl pkcs12 -in mysite.pfx -clcerts -nokeys -out certificate-VPS.pem
我最终得到了 private-key-VPS.pem 和 certificate-VPS.pem 文件
我知道获取 mysite.pfx 的步骤与@CodeFuller 所描述的略有不同,但到目前为止一切顺利吗?
然后我添加了代码:
Dim certificate As X509Certificate2 = New X509Certificate2("C:\temp\_certificates\prodserverV2\mysite.pfx", "mypwd")
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)
但我得到 4 个错误:
GetRSAPrivateKey' 不是“X509Certificate2”的成员。
“SignData”不是“RSA”的成员。
'HashAlgorithmName' 未声明。由于其保护级别,它可能无法访问。
未声明“RSASignaturePadding”。由于其保护级别,它可能无法访问。
更新 2
感谢@CodeFuller!我的目标是框架 4.6.1,现在似乎更进一步。我最终得到一个这样的 URL:https://www-mysite-com.cdn.ampproject.org/update-cache/c/s/www.mysite.com/articles/270/newarticle1/amp?amp_action=flush&_ts=1522939248&_url_signature=U30zdGVtLkJ5uGVbRQ==。我现在如何检查它是否是有效的 URL?
我正在检查this page 上的“生成 RSA 密钥”部分,但我很困惑,因为我实际上已经对这些步骤进行了编码吗?如何检查我现在最终使用的 URL 是否有效?
更新 3
好的,我尝试了您的新代码。仍然得到URL signature verification error。我尝试了我文章的/amp URL 和我的URL 中没有/amp 部分。两者都会导致相同的 URL 签名验证错误。
我注意到,当我将最终 URL 打印到我的网站(参见下面的代码)时,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&_ts=1523094395&_url_signature=U3lzdGVrLkn5dGVbXQ==
注意参数应该是amp_ts和amp_url_signature,现在它们分别是_ts和_url_signature。
在调用 Google 之前,我尝试通过手动将参数 _ts 和 _url_signature 重命名为 amp_ts 和 amp_url_signature 来编辑 URL。但我想这会导致签名和实际 URL 之间的差异。难道是我的代码以某种方式破坏了& 字符,因此当我稍后手动重命名这些字符时,它总是会导致签名验证?你看到我可以在我的代码中修复什么了吗?
顺便说一句:在签署 URL 之前,我尝试在代码隐藏中将 & 替换为 %26,但随后出现 Google 404 错误:
请求的 URL /update-cache/c/s/www.toptrouwen.nl/artikelen/132/het-uitwisselen-van-de-trouwringen-hoe-voorkom-je-bloopers/amp?amp_action=flush%26amp_ts =1523094395%26amp_url_signature=U3lzdGVrLkJ1dGVbXQ== 在此服务器上未找到。这就是我们所知道的。
我的代码:
Dim ampBaseUrl As String = "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?amp_action=flush&_ts=" + tStamp
Dim rsa As RSA = certificate.GetRSAPrivateKey()
Dim data() As Byte = System.Text.Encoding.ASCII.GetBytes(signatureUrl)
Dim sig() As Byte = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)
Dim AMPURLSignature As String = EncodeTo64(sig.ToString)
Dim url As String = ampBaseUrl + signatureUrl + "&_url_signature=" + AMPURLSignature
ltStatus.Text = "AMP URL:<a target='_blank' href='" + url + "'>" + url + "</a>"
此外,我确定此页面存在于 Google AMP 缓存中,因为我可以在我的移动设备上的 Google 搜索结果中看到并请求它。
更新 4
我想我已经接近了,还可以得到一些额外的帮助,请参阅此处:https://github.com/ampproject/amphtml/issues/14483#issuecomment-380549060
我现在正在尝试让其他人也更容易测试:我现在运行以下命令来获取公钥和私钥,而不是依赖于我的 SSL
openssl genrsa 2048 > private-key.pem
openssl rsa -in private-key.pem -pubout >public-key.pem
我现在有文件 private-key.pem 和 public-key.pem
我会将public-key.pem 重命名为apikey.pub 并将其放在https://example.com/.well-known/amphtml/apikey.pub 上
我想采用@CodeFuller 推荐的最简单方法并创建一个.pfx 文件,然后我可以将其加载到X509Certificate2 类型的变量中。
当我运行这个命令时:openssl pkcs12 -export -out keys.pfx -inkey private-key.pem -in public-key.pem
我收到错误:unable to load certificates
但是这次我没有.crt 文件,只有public-key.pem。如何获得.pfx 文件?我已经检查了here。
【问题讨论】:
标签: asp.net ssl certificate rsa google-amp