Hasilkan iklan bertanda tangan untuk SKAdnetwork di c# .net

Mengikuti apple SKADNetwork Saya telah membuat kunci pribadi dan kunci publik dengan perintah ini

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

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

saya dapat membuat tanda tangan yang valid dengan python mengikuti proyek ini https://github.com/singular-labs/Singular-SKAdNetwork-App/tree/master/skadnetwork-server

Tetapi ketika saya mencoba membuat tanda tangan melalui perpustakaan c# bouncycastle saya mendapatkan hasil yang berbeda jika saya menggunakan data yang sama.

UJI BOUNCYCASTLE

 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;
    }

UJI .NET CORE 3

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

        }

Dengan pengujian .net.core, hasilnya bahkan lebih buruk lagi karena token berubah pada setiap eksekusi. Saya pikir ada perilaku acak.

#FORMAT UJI DETERMINISTIK BOUNCYCASTLE R|S dan 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)
            {
            }

Masih mendapatkan hasil yang berbeda dari pustaka python FastECDSA jika string inputnya sama.

SOLUSI PEMBARUAN: terima kasih kepada komentar @topaco

            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)
            {
            }

person Riccardo    schedule 22.02.2021    source sumber
comment
Apakah kode Python memberikan tanda tangan yang sama (seperti kode BC) setiap kali dijalankan atau tanda tangan yang berbeda (seperti kode .NET)? Perhatikan bahwa ada ECDSA deterministik (RFC6979) dan non-deterministik. Keduanya dapat diandalkan dan memberikan tanda tangan yang sah.   -  person user 9014097    schedule 22.02.2021
comment
@topaco saya berasumsi bahwa python menggunakan RFC6979 karena memberikan tanda tangan yang sama setiap kali. Saya telah menemukan cara ini untuk menggunakan ECDSA ECDsaSigner signer = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest())); stackoverflow.com/ pertanyaan/51592748/   -  person Riccardo    schedule 22.02.2021
comment
@Topaco jika saya menggunakan RFC6979 sistem Python dan C# saya mendapatkan hasil yang berbeda (tetapi hasil yang sama dengan input yang sama di sistem yang sama): apakah ini perilaku yang diharapkan?   -  person Riccardo    schedule 22.02.2021
comment
Kedua implementasi dari pertanyaan Anda menggunakan varian non-deterministik, karena keduanya menghasilkan tanda tangan yang berbeda setiap kali. Namun kedua implementasi tersebut menerapkan format tanda tangan berbeda, kode .NET/BC menggunakan ASN.1 DER, kode .NET murni (r|s). Pendekatan yang diposting di komentar pertama Anda memang menerapkan algoritma deterministik dalam format (r|s). Jika kode Python juga menggunakan varian deterministik, saya berharap tanda tangannya cocok. Namun sebagai perbandingan, formatnya harus cocok, jadi konversi mungkin diperlukan tergantung pada format Python.   -  person user 9014097    schedule 22.02.2021
comment
Python menggunakan perpustakaan FastECDSA github.com /singular-labs/Singular-SKAdNetwork-App/blob/master/ Karena hasilnya masih berbeda antara sistem python dan comment1(bouncycastle deterministic(r|s)) saya akan mencoba menormalkan ke format yang sama   -  person Riccardo    schedule 22.02.2021
comment
@Topaco semuanya jelas, terima kasih. Saya telah memperbarui pertanyaan dengan tes terakhir tetapi saya masih tidak dapat memperoleh hasil yang sama dengan yang saya dapatkan di server python.   -  person Riccardo    schedule 22.02.2021
comment
ECDsaSigner tidak melakukan hash secara implisit, yaitu Anda harus meng-hash pesan dalam kode C# secara eksplisit dengan SHA256 sebelum menandatangani. Kemudian hasil dari kode Python dan C# sama di mesin saya.   -  person user 9014097    schedule 22.02.2021
comment
@Topaco terima kasih banyak, sekarang berfungsi!   -  person Riccardo    schedule 22.02.2021