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 を 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