I'm struggling getting the signing part of sending server 2 sever requests working from .Net/c#
I'm struggling to build the header X-Apple-CloudKit-Request-Signaturev1
Has anyone had any joy getting this working (I know announcement was only about 3 days ago)
:-)
I have tried it a few Days with no success if using the Build-In Functions. Now a tried it with the Bouncy Castle Lib (https://www.bouncycastle.org) an then it worked... here is my code for testing:
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
namespace CloudKitTester
{
public class CloudKitHelper
{
private string _keyID;
private string _container;
private string _environment;
private AsymmetricCipherKeyPair _dsaKeyPair;
private string _apiVersion = "1";
public CloudKitHelper(string pemFilePath, string keyID, string container, string environment = "development")
{
_keyID = keyID;
_container = container;
_environment = environment;
using (var reader = File.OpenText(pemFilePath))
{
var pemReader = new PemReader(reader);
_dsaKeyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
}
}
public string Request(string query, string jsonData = "")
{
SHA256Cng sha256 = new SHA256Cng();
var serverPath = String.Format("/database/{0}/{1}/{2}/public/{3}", _apiVersion, _container, _environment, query);
var requestBodyBinary = Encoding.UTF8.GetBytes(jsonData);
var requestBodyHashBase64 = Convert.ToBase64String(sha256.ComputeHash(requestBodyBinary));
var time = String.Format("{0}Z", DateTime.UtcNow.ToString("s"));
var signatureString = String.Format("{0}:{1}:{2}", time, requestBodyHashBase64, serverPath);
var signatureBinary = Encoding.UTF8.GetBytes(signatureString);
var ecDSASigner = SignerUtilities.GetSigner("SHA256withECDSA");
ecDSASigner.Init(true, _dsaKeyPair.Private);
ecDSASigner.BlockUpdate(signatureBinary, 0, signatureBinary.Length);
var signatureBase64 = Convert.ToBase64String(ecDSASigner.GenerateSignature());
var request = HttpWebRequest.Create(String.Format("https://api.apple-cloudkit.com{0}", serverPath));
request.Method = "POST";
request.ContentType = "text/plain";
request.Headers.Add("X-Apple-CloudKit-Request-SignatureV1", signatureBase64);
request.Headers.Add("X-Apple-CloudKit-Request-KeyID", _keyID);
request.Headers.Add("X-Apple-CloudKit-Request-ISO8601Date", time);
using (var stream = request.GetRequestStream())
{
stream.Write(requestBodyBinary, 0, requestBodyBinary.Length);
}
try
{
var response = (HttpWebResponse) request.GetResponse();
using (var output = new StreamReader(response.GetResponseStream()))
{
return output.ReadToEnd();
}
}
catch
{
return null;
}
}
}
class Program
{
static void Main(string[] args)
{
var pathToPemFile = "eckey.pem";
var keyIDfromCloudKitDashboard = "2c384ea...";
var cloudKitContainer = "iCloud.com.....";
var helper = new CloudKitHelper(pathToPemFile, keyIDfromCloudKitDashboard, cloudKitContainer);
var recordsJSON = helper.Request("records/query", "{\"query\":{\"recordType\":\"News\"}}");
Debug.Print(recordsJSON);
}
}
}