Apple 发布了一种针对 CloudKit 的服务器到服务器进行身份验证的新方法。https://developer.apple.com/library/content/documentation/DataManagement/Conceptual/CloudKitWebServicesReference/SettingUpWebServices.html#//apple_ref/doc/uid/TP40015240-CH24-SW6
我试图针对 CloudKit 和这种方法进行身份验证。起初我生成了密钥对并将公钥提供给 CloudKit,到目前为止没有问题。
我开始构建请求标头。根据文档,它应该如下所示:
X-Apple-CloudKit-Request-KeyID: [keyID]
X-Apple-CloudKit-Request-ISO8601Date: [date]
X-Apple-CloudKit-Request-SignatureV1: [signature]
- [keyID],没问题。您可以在 CloudKit 仪表板中找到它。
- [日期],我认为这应该工作:2016-02-06T20:41:00Z
- [签名],问题来了……
文档说:
在步骤 1 中创建的签名。
步骤 1 说:
连接以下参数并用冒号分隔它们。
[Current date]:[Request body]:[Web Service URL]
我问自己“为什么我必须生成密钥对?”。
但是第2步说:
使用您的私钥计算此消息的 ECDSA 签名。
也许他们的意思是用私钥签署连接签名并将其放入标题中?反正我两个都试过了...
这个(无符号)签名值的示例如下所示:
2016-02-06T20:41:00Z:YTdkNzAwYTllNjI1M2EyZTllNDNiZjVmYjg0MWFhMGRiMTE2MjI1NTYwNTA2YzQyODc4MjUwNTQ0YTE5YTg4Yw==:https://api.apple-cloudkit.com/database/1/[iCloud Container]/development/public/records/lookup
请求正文值经过 SHA256 散列,然后经过 base64 编码。我的问题是,我应该用“:”连接,但网址和日期也包含“:”。这是正确的吗?(我还尝试对 URL 进行 URL 编码并删除日期中的“:”)。
接下来,我用 ECDSA 签署了这个签名字符串,将其放入标头并发送。但我总是得到 401“身份验证失败”。为了签署它,我使用了ecdsa python 模块,带有以下命令:
from ecdsa import SigningKey
a = SigningKey.from_pem(open("path_to_pem_file").read())
b = "[date]:[base64(request_body)]:/database/1/iCloud....."
print a.sign(b).encode('hex')
也许python模块不能正常工作。但它可以从私钥生成正确的公钥。所以我希望其他功能也能工作。
有没有人设法使用服务器到服务器的方法对 CloudKit 进行身份验证?它是如何正常工作的?
编辑:正确的python版本有效
from ecdsa import SigningKey
import ecdsa, base64, hashlib
a = SigningKey.from_pem(open("path_to_pem_file").read())
b = "[date]:[base64(sha256(request_body))]:/database/1/iCloud....."
signature = a.sign(b, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_der)
signature = base64.b64encode(signature)
print signature #include this into the header