ios – C# code for generating a signature for Apple promotions offer is producing an invalid signature


I try generate signature with the below code to be used from mobile side in Apple store but the generated signature is invalid.

Apple Link: https://developer.apple.com/documentation/storekit/in-app_purchase/subscriptions_and_offers/generating_a_signature_for_promotional_offers

My Code:

 var nonce = Guid.NewGuid().ToString().ToLower();
            long timestamp = (long)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds;

            string payload = request.AppBundleID + "\u2063" + request.KeyIdentifier + "\u2063" + request.ProductIdentifier + "\u2063" + request.OfferIdentifier + "\u2063" + request.ApplicationUsername + "\u2063" + nonce + "\u2063" + timestamp;


            string keyP8Base64 = System.IO.File.ReadAllText(Path.Combine(webHostEnvironment.WebRootPath, "FileName.p8"))
                                   .Replace("-----BEGIN PRIVATE KEY-----", "")
                                   .Replace("-----END PRIVATE KEY-----", "")
                                   .Replace("\n", "")
                                   .Replace("\r", "");

            byte[] keyP8Bytes = Convert.FromBase64String(keyP8Base64);

            var privateKey = CngKey.Import(keyP8Bytes, CngKeyBlobFormat.Pkcs8PrivateBlob);

            using (ECDsaCng dsa = new ECDsaCng(privateKey))
            {
                dsa.HashAlgorithm = CngAlgorithm.Sha256;
                var unsignedData = Encoding.UTF8.GetBytes(payload);

                // Sign data
                var signature = dsa.SignData(unsignedData);

                // Convert signature to ASN.1 format
                var r = new BigInteger(signature.Take(32).ToArray(), isUnsigned: true, isBigEndian: true);
                var s = new BigInteger(signature.Skip(32).ToArray(), isUnsigned: true, isBigEndian: true);

                var rBytes = r.ToByteArray();
                var sBytes = s.ToByteArray();

                if (rBytes.Length > 1 && rBytes[0] == 0)
                    rBytes = rBytes.Skip(1).ToArray();
                if (sBytes.Length > 1 && sBytes[0] == 0)
                    sBytes = sBytes.Skip(1).ToArray();

                var derSignature = new byte[6 + rBytes.Length + sBytes.Length];
                derSignature[0] = 0x30; // ASN.1 sequence tag
                derSignature[1] = (byte)(4 + rBytes.Length + sBytes.Length); // Length of the sequence
                derSignature[2] = 0x02; // Integer tag for r
                derSignature[3] = (byte)rBytes.Length; // Length of r
                Buffer.BlockCopy(rBytes, 0, derSignature, 4, rBytes.Length);
                derSignature[4 + rBytes.Length] = 0x02; // Integer tag for s
                derSignature[5 + rBytes.Length] = (byte)sBytes.Length; // Length of s
                Buffer.BlockCopy(sBytes, 0, derSignature, 6 + rBytes.Length, sBytes.Length);

                var derSignatureString = Convert.ToBase64String(derSignature);


                if (dsa.VerifyData(unsignedData, signature))
                {

                    return new PromoSignatureResponse
                    {

                        KeyIdentifier = request.KeyIdentifier,
                        Nonce = nonce,
                        Signature = derSignatureString,
                        Timestamp = timestamp.ToString()
                    };
                }

Example of the generated signature which is invalid be Apple Store: “MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvcYI0Wg2vrkuK6jzPNf1qUSkTJeYSNKzu3hJSJhKXuH7c2NMD7QomM5yTdXhs4GFGNmaAPhjS3p3mOXcabfW9g==”

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img