CloudKit服务器到服务器的身份验证 [英] CloudKit Server-to-Server authentication

查看:265
本文介绍了CloudKit服务器到服务器的身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨日公布的苹果公司的新方法对抗CloudKit验证,服务器到服务器。 <一href=\"https://developer.apple.com/library/$p$prelease/ios/documentation/DataManagement/Conceptual/CloutKitWebServicesReference/SettingUpWebServices/SettingUpWebServices.html#//apple_ref/doc/uid/TP40015240-CH24-SW6\">https://developer.apple.com/library/$p$prelease/ios/documentation/DataManagement/Conceptual/CloutKitWebServicesReference/SettingUpWebServices/SettingUpWebServices.html#//apple_ref/doc/uid/TP40015240-CH24-SW6

今天,我想对CloudKit这种方法进行身份验证。起初我生成的密钥对,给了公钥CloudKit,没有问题为止。

我开始建立请求头。根据文档就应该是这样的:

  X-苹果CloudKit请求-的KeyID:[KEYID]
的X苹果CloudKit请求-ISO8601Date:[日期]
的X苹果CloudKit请求-SignatureV1:[签名]


  • [KEYID],没有问题。您可以在仪表盘CloudKit找到这个。

  • [日期],我想这应该工作:2016-02-06T20:41:00Z

  • [签名],这里的问题...

该文件说:


  

在步骤中创建的签名1.


步骤1说:


  

连接以下参数,并将它们用冒号分开。结果
   [当前日期]:请求正文]:[Web服务URL]


我问自己我为什么要生成密钥对?结果
但第2步说:


  

计算此消息的ECDSA签名用你的私钥。


也许他们签署与私钥签名级联,并把这一进头?无论如何,我都试过...

我给这(无符号)签名值样本如下:

<$p$p><$c$c>2016-02-06T20:41:00Z:YTdkNzAwYTllNjI1M2EyZTllNDNiZjVmYjg0MWFhMGRiMTE2MjI1NTYwNTA2YzQyODc4MjUwNTQ0YTE5YTg4Yw==:https://api.apple-cloudkit.com/database/1/[iCloud容器] /开发/公/记录/查询

请求正文值为SHA256散列和连接的base64 codeD之后。我的问题是,我应该用串联:但是URL和日期也包含:。这是对的吗? (我也试图URL恩code中的URL,并删除:在日期)。结果
在接下来的我ECDSA签署此签名串,把它放到头和发送。但是,我总是得到401验证失败回来。要签字,我用了 ECDSA Python模块,用下面的命令:

 从ECDSA进口SigningKey
A = SigningKey.from_pem(开放(path_to_pem_file)。阅读())
B =[日期]:[BASE64(request_body)] /数据库/ 1 / iCloud中.....
打印a.sign(二).EN code(十六进制)

也许Python模块不能正常工作。但它可以产生从私钥右公钥。所以我希望等功能也工作。

有没有人管理与服务器到服务器的方法对CloudKit认证?它是如何正常工作?

编辑:正确的python版本的作品

 从ECDSA进口SigningKey
进口ECDSA,BASE64,hashlibA = SigningKey.from_pem(开放(path_to_pem_file)。阅读())
B =[日期]:[BASE64(SHA256(request_body))]:/数据库/ 1 / iCloud中.....
签名= a.sign(B,hashfunc = hashlib.sha256,SIGEN code = ecdsa.util.sigen code_der)
签名= base64.b64en code(签字)
打印签名#包含进这个头


解决方案

消息的最后一部分

  [当前日期]:请求正文]:[Web服务URL]

不得的包含域(它的必须的包括任何查询参数):

<$p$p><$c$c>2016-02-06T20:41:00Z:YTdkNzAwYTllNjI1M2EyZTllNDNiZjVmYjg0MWFhMGRiMTE2MjI1NTYwNTA2YzQyODc4MjUwNTQ0YTE5YTg4Yw==:/database/1/[iCloud容器] /开发/公/记录/查询

使用新行更好的可读性:

  2016-02-06T20:41:00Z
:YTdkNzAwYTllNjI1M2EyZTllNDNiZjVmYjg0MWFhMGRiMTE2MjI1NTYwNTA2YzQyODc4MjUwNTQ0YTE5YTg4Yw ==
:/数据库/ 1 / [iCloud的容器] /开发/公/记录/查询

下面介绍如何计算伪code标头值

确切的API调用取决于你所使用的具体的语言和加密库。

  // 1。日期
//例:2016-02-07T18:58:24Z
//陷阱:确保不包括毫秒
日期= isoDateWithoutMilliseconds()// 2。有效载荷
//例(空字符串的base64 EN codeD,GET请求):
// 47DEQpj8HBSa + / + TIMW = 5JCeuQeRkm5NMpJWZG3hSuFU
//陷阱:确保输出的base64是连接codeD(不是十六进制)
有效载荷= base64en code(SHA256(体))// 3。路径
//例:/数据库/ 1 / [containerIdentifier] /开发/公/记录/查询
//陷阱:不要包含域名;不包括任何查询参数
PATH = stripDomainKeepQueryParams(URL)// 4。信息
//注册日期,有效载荷和路径用冒号
消息=日期+:+有效载荷+:+路径// 5。计算使用您的私人密钥对消息的签名。
//这一步看起来每种语言/ lib目录加密很大的不同。
//陷阱:确保输出的base64是连接codeD。
//提示:密钥本身包含的签名算法信息
//(在你的NodeJS可以使用签名名称'RSA-SHA256'来计算
//与ECDSA键选择正确的ECDSA签名)。
签名= base64en code(符号(消息,键))// 6。设置头
的X苹果CloudKit请求-的KeyID = KEYID
的X苹果CloudKit请求-ISO8601Date =日期
的X苹果CloudKit请求-SignatureV1 =签名// 7。对于POST请求,不要忘了实际发送签名请求正文
//(不仅仅是头)

Yesterday Apple published a new method to authenticate against CloudKit, server-to-server. https://developer.apple.com/library/prerelease/ios/documentation/DataManagement/Conceptual/CloutKitWebServicesReference/SettingUpWebServices/SettingUpWebServices.html#//apple_ref/doc/uid/TP40015240-CH24-SW6

Today I tried to authenticate against CloudKit and this method. At first I generated the key pair and gave the public key to CloudKit, no problem so far.

I started to build the request header. According to the documentation it should look like this:

X-Apple-CloudKit-Request-KeyID: [keyID]  
X-Apple-CloudKit-Request-ISO8601Date: [date]  
X-Apple-CloudKit-Request-SignatureV1: [signature]

  • [keyID], no problem. You can find this in the CloudKit dashboard.
  • [Date], I think this should work: 2016-02-06T20:41:00Z
  • [signature], here is the problem...

The documentation says:

The signature created in Step 1.

Step 1 says:

Concatenate the following parameters and separate them with colons.
[Current date]:[Request body]:[Web Service URL]

I asked myself "Why do I have to generate the key pair?".
But step 2 says:

Compute the ECDSA signature of this message with your private key.

Maybe they mean to sign the concatenated signature with the private key and put this into the header? Anyway I tried both...

My sample for this (unsigned) signature value looks like:

2016-02-06T20:41:00Z:YTdkNzAwYTllNjI1M2EyZTllNDNiZjVmYjg0MWFhMGRiMTE2MjI1NTYwNTA2YzQyODc4MjUwNTQ0YTE5YTg4Yw==:https://api.apple-cloudkit.com/database/1/[iCloud Container]/development/public/records/lookup  

The request body value is SHA256 hashed and after that base64 encoded. My question is, I should concatenate with a ":" but the url and the date also contains ":". Is it correct? (I also tried to URL-Encode the URL and delete the ":" in the date).
At next I signed this signature string with ECDSA, put it into the header and send it. But I always get 401 "Authentication failed" back. To sign it, I used the ecdsa python module, with following commands:

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')

Maybe the python module doesn't work correctly. But it can generate the right public key from the private key. So I hope the other functions also work.

Has anybody managed to authenticate against CloudKit with the server-to-server method? How does it work correctly?

Edit: Correct python version that works

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

解决方案

The last part of the message

[Current date]:[Request body]:[Web Service URL]

must not include the domain (it must include any query parameters):

2016-02-06T20:41:00Z:YTdkNzAwYTllNjI1M2EyZTllNDNiZjVmYjg0MWFhMGRiMTE2MjI1NTYwNTA2YzQyODc4MjUwNTQ0YTE5YTg4Yw==:/database/1/[iCloud Container]/development/public/records/lookup

With newlines for better readability:

2016-02-06T20:41:00Z
:YTdkNzAwYTllNjI1M2EyZTllNDNiZjVmYjg0MWFhMGRiMTE2MjI1NTYwNTA2YzQyODc4MjUwNTQ0YTE5YTg4Yw==
:/database/1/[iCloud Container]/development/public/records/lookup

The following shows how to compute the header value in pseudocode

The exact API calls depend on the concrete language and crypto library you use.

//1. Date
//Example: 2016-02-07T18:58:24Z
//Pitfall: make sure to not include milliseconds
date = isoDateWithoutMilliseconds() 

//2. Payload
//Example (empty string base64 encoded; GET requests):
//47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
//Pitfall: make sure the output is base64 encoded (not hex)
payload = base64encode(sha256(body))  

//3. Path
//Example: /database/1/[containerIdentifier]/development/public/records/lookup
//Pitfall: Don't include the domain; do include any query parameter
path = stripDomainKeepQueryParams(url) 

//4. Message
//Join date, payload, and path with colons
message = date + ':' + payload + ':' + path

//5. Compute a signature for the message using your private key.
//This step looks very different for every language/crypto lib.
//Pitfall: make sure the output is base64 encoded.
//Hint: the key itself contains information about the signature algorithm 
//      (on NodeJS you can use the signature name 'RSA-SHA256' to compute a 
//      the correct ECDSA signature with an ECDSA key).
signature = base64encode(sign(message, key))

//6. Set headers
X-Apple-CloudKit-Request-KeyID = keyID 
X-Apple-CloudKit-Request-ISO8601Date = date  
X-Apple-CloudKit-Request-SignatureV1 = signature

//7. For POST requests, don't forget to actually send the unsigned request body
//   (not just the headers)

这篇关于CloudKit服务器到服务器的身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆