สร้างโฆษณาที่ลงนามสำหรับ SKAdnetwork ใน c# .net

ติดตาม apple SKADNetwork ฉันได้สร้างรหัสส่วนตัวและรหัสสาธารณะด้วยคำสั่งนี้

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

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

ฉันสามารถสร้างลายเซ็นที่ถูกต้องด้วย python ตามโครงการนี้ https://github.com/singular-labs/Singular-SKAdNetwork-App/tree/master/skadnetwork-server

แต่เมื่อฉันพยายามสร้างลายเซ็นผ่านไลบรารี c# bouncycastle ฉันจะได้ผลลัพธ์ที่แตกต่างออกไปหากฉันใช้ข้อมูลเดียวกัน

การทดสอบ 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;
    }

การทดสอบ .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);

        }

ด้วยการทดสอบ .net.core ผลลัพธ์จะแย่ยิ่งกว่าเดิมเนื่องจากโทเค็นมีการเปลี่ยนแปลงในการดำเนินการแต่ละครั้ง ฉันคิดว่ามีพฤติกรรมสุ่ม

#BOUNCYCASTLE รูปแบบการทดสอบที่กำหนด R|S และ 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)
            {
            }

ยังคงมีผลลัพธ์ที่แตกต่างจากไลบรารี python FastECDSA หากสตริงอินพุตเป็นสตริงเดียวกัน

โซลูชันการอัปเดต: ขอบคุณความคิดเห็น @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 แหล่งที่มา
comment
รหัส Python มีลายเซ็นเดียวกัน (เป็นรหัส BC) ทุกครั้งที่มีการดำเนินการหรือลายเซ็นอื่น (เป็นรหัส .NET) หรือไม่ โปรดทราบว่ามี ECDSA ที่กำหนดขึ้น (RFC6979) และ ECDSA ที่ไม่สามารถกำหนดได้ ทั้งสองมีความน่าเชื่อถือและมีลายเซ็นที่ถูกต้อง   -  person user 9014097    schedule 22.02.2021
comment
@topaco ฉันคิดว่า python ใช้ RFC6979 เนื่องจากมีลายเซ็นเดียวกันในแต่ละครั้ง ฉันพบวิธีนี้แล้วในการใช้ ECDSA ECDsaSigner signer ที่กำหนดขึ้น = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest())); stackoverflow.com/ คำถาม/51592748/   -  person Riccardo    schedule 22.02.2021
comment
@Topaco ถ้าฉันใช้ RFC6979 ทั้งระบบ Python และ C# ฉันมีผลลัพธ์ที่แตกต่างกัน (แต่ผลลัพธ์เดียวกันกับอินพุตเดียวกันในระบบเดียวกัน): นี่เป็นพฤติกรรมที่คาดหวังหรือไม่   -  person Riccardo    schedule 22.02.2021
comment
การใช้งานทั้งสอง จากคำถามของคุณ ใช้รูปแบบที่ไม่สามารถกำหนดได้ เนื่องจากทั้งสองส่งกลับลายเซ็นที่แตกต่างกันในแต่ละครั้ง แต่การใช้งานทั้งสองใช้รูปแบบลายเซ็นต่างกัน รหัส .NET/BC ใช้ ASN.1 DER ซึ่งเป็นโค้ด .NET แท้ (r|s) แนวทางที่โพสต์ในความคิดเห็นแรกของคุณใช้อัลกอริทึมที่กำหนดขึ้นในรูปแบบ (r|s) หากโค้ด Python ใช้ตัวแปรที่กำหนดขึ้นด้วย ฉันคาดว่าลายเซ็นจะตรงกัน อย่างไรก็ตาม สำหรับการเปรียบเทียบ รูปแบบจะต้องตรงกัน ดังนั้นอาจจำเป็นต้องแปลง ทั้งนี้ขึ้นอยู่กับรูปแบบ Python   -  person user 9014097    schedule 22.02.2021
comment
Python กำลังใช้ไลบรารี FastECDSA github.com /singular-labs/Singular-SKAdNetwork-App/blob/master/ เนื่องจากผลลัพธ์ยังคงแตกต่างกันระหว่างระบบ python และ comment1(bouncycastle deterministic(r|s)) ฉันจะพยายามทำให้เป็นมาตรฐานในรูปแบบเดียวกัน   -  person Riccardo    schedule 22.02.2021
comment
@Topaco ชัดเจนขอบคุณ ฉันได้อัปเดตคำถามด้วยการทดสอบครั้งล่าสุด แต่ฉันยังคงไม่สามารถได้ผลลัพธ์แบบเดียวกับที่ฉันมีในเซิร์ฟเวอร์ python   -  person Riccardo    schedule 22.02.2021
comment
ECDsaSigner ไม่ได้แฮชโดยปริยาย กล่าวคือ คุณต้องแฮชข้อความในโค้ด C# อย่างชัดเจนด้วย SHA256 ก่อนลงนาม ผลลัพธ์จากโค้ด Python และ C# จะเหมือนกันบนเครื่องของฉัน   -  person user 9014097    schedule 22.02.2021
comment
@Topaco ขอบคุณมาก มันใช้งานได้แล้ว!   -  person Riccardo    schedule 22.02.2021