Generate signed ads for SKAdnetwork in c# .net

233 Views Asked by At

Following apple SKADNetwork I've generated private key and public key with this command

openssl ecparam -name prime192v1 -genkey -noout -out private_key.pem

openssl ec -in private_key.pem -pubout -out public_key.pem

i'm able to generate a valid signature with python following this project https://github.com/singular-labs/Singular-SKAdNetwork-App/tree/master/skadnetwork-server

But when i'm trying to generate signature via c# bouncycastle library i have different results if i use same data.

BOUNCYCASTLE TEST

 public static AsymmetricCipherKeyPair ReadAsymmetricPrivateKeyParameter(string pemFilename)
    {
        var fileStream = System.IO.File.OpenText(pemFilename);
        var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(fileStream);
        var KeyParameter = (AsymmetricCipherKeyPair)pemReader.ReadObject();
        return (AsymmetricCipherKeyPair)KeyParameter;
    }

    static void Main(string[] args)
    {
        AsymmetricCipherKeyPair pkey = ReadAsymmetricPrivateKeyParameter("private_key.pem");

        string pars = getParamsSignature("2.0", "xxxxxxx.skadnetwork", "10", "302584613", "0a97ad57-87d1-49e7-b166-9152c708251b", "1613749507007", "0");

        Sign(pkey, "", pars);
        Console.Read();
    }

    static string getParamsSignature(string version, string ad_network_id, string campaign_id, string target_app_id, string nonce, string timestamp, string source_app_id)
    {
        string[] p = new string[] {
        version,
        ad_network_id,
        campaign_id,
        target_app_id,
        nonce,
        source_app_id,
        timestamp
        };
        return string.Join("\u2063", p);
    }

    public static bool Sign(AsymmetricCipherKeyPair pubKey,  string msg)
    {
        try
        {

            ECDomainParameters aa;
            byte[] msgBytes = Encoding.UTF8.GetBytes(msg);

            ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");

            signer.Init(true, pubKey.Private);

            signer.BlockUpdate(msgBytes, 0, msgBytes.Length);

            byte[] sigBsdytes = signer.GenerateSignature();

           
            var signature = Convert.ToBase64String(sigBsdytes);



            //MDUCGQDgqw1YQN/vvHTxXXTpovNYUnACzkFrXJwCGCXAnr3TUbbqIUr6cBamymrypcQET5RR7Q==


        }
        catch (Exception exc)
        {
            Console.WriteLine("Verification failed with the error: " + exc.ToString());
            return false;
        }
        return false;
    }

.NET CORE 3 TEST

static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");


            string pars = getParamsSignature("2.0", "xxxxx.skadnetwork", "10", "302584613", "0a97ad57-87d1-49e7-b166-9152c708251b", "1613749507007", "0");

            //bool aaaaa = VerifySignature(aa, attribution_signature, pars);
            string eccPem = File.ReadAllText("private_key.pem");


            var key = ECDsa.Create(ECCurve.CreateFromValue("1.2.840.10045.3.1.1"));
            key.ImportECPrivateKey(Convert.FromBase64String(eccPem), out _);
         
            var signed = key.SignData(Encoding.UTF8.GetBytes(pars), HashAlgorithmName.SHA256);
            var hash = Convert.ToBase64String(signed);

        }

With .net.core test the result is even worst as the token change at each execution. I think there's a random behavior.

#BOUNCYCASTLE DETERMINISTIC TEST FORMAT R|S and ASN1

            byte[] msgBytes = Encoding.UTF8.GetBytes(msg);


            ECDsaSigner signer = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest()));
            signer.Init(true, pubKey.Private);
            var sigBsdytes = signer.GenerateSignature(msgBytes);


            //SIGNATURE (R|S)
            Console.WriteLine( Convert.ToBase64String(sigBsdytes.SelectMany(a => a.ToByteArray()).ToArray()));


            //SIGNATURE (ASN1)
            var s = new MemoryStream();
            try
            {
                DerSequenceGenerator seq = new DerSequenceGenerator(s);

                seq.AddObject(new DerInteger(sigBsdytes[0]));
                seq.AddObject(new DerInteger(sigBsdytes[1]));
                seq.Close();

                
                var signature = Convert.ToBase64String(s.ToArray());

                Console.WriteLine(signature);
            }
            catch (IOException e)
            {
            }

Still having a different result from python FastECDSA library if the input string is the same one.

UPDATE SOLUTION: thanks to @topaco comment

            var crypt = new System.Security.Cryptography.SHA256Managed();
            byte[] msgBytes = crypt.ComputeHash(Encoding.UTF8.GetBytes(msg));

            ECDsaSigner signer = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest()));
            signer.Init(true, pubKey.Private);
            var sigBsdytes = signer.GenerateSignature(msgBytes);

            //SIGNATURE (ASN1)
            var s = new MemoryStream();
            try
            {
                DerSequenceGenerator seq = new DerSequenceGenerator(s);

                seq.AddObject(new DerInteger(sigBsdytes[0]));
                seq.AddObject(new DerInteger(sigBsdytes[1]));
                seq.Close();


                var signature = Convert.ToBase64String(s.ToArray());

                Console.WriteLine(signature);
            }
            catch (IOException e)
            {
            }
0

There are 0 best solutions below