يُرجع SignedXml.CheckSignature صحيحًا فقط إذا قمت بالتحقق باستخدام المفتاح الخاص

StackOverflow https://stackoverflow.com//questions/21005978

سؤال

لقد رأيت العديد من الأسئلة المشابهة ولكن لا شيء يتناول بالضبط ما أطرحه.

أحاول التوقيع على XML ثم التحقق منه باستخدام المفتاح العام باستخدام C#.

أقوم بتوقيع XML باستخدام مفتاح ثم تصدير المفتاح إلى XML.ثم خذ المفتاح وXML الموقع إلى كمبيوتر آخر، وقم باستيراد المفتاح باستخدامه rsa.FromXmlString(doc.InnerXml), وتحقق من توقيع XML.

يعمل هذا إذا قمت بتصدير المفاتيح العامة والخاصة إلى ملف XML باستخدام rsa.ToXmlString(True).ومع ذلك، أريد تصدير مفتاحي العام فقط باستخدام rsa.ToXmlString(False).إذا قمت بتصدير المفتاح العام فقط واستيراده على الكمبيوتر الثاني وحاولت التحقق من صحة توقيع XML، فسيقول أن التوقيع غير صالح.

أولاً، هل يجب أن أكون قادرًا على التحقق من ملف XML الموقع باستخدام المفتاح العام فقط؟

ثانيًا، إذا كان هذا صحيحًا، فلماذا تعمل وظيفة التحقق من XML الخاصة بي فقط مع زوج المفاتيح pub/priv وليس مع المفتاح العام فقط؟

هل لديك أي حكمة حول كيفية تصحيح هذه المشكلة؟لست متأكدًا مما يجب فعله أيضًا بسبب signedXml.CheckSignature(Key); لا يقدم أي معلومات حول سبب فشله.

يوجد أدناه مفتاح الاستيراد ومفتاح التصدير وتوقيع XML والتحقق من وظائف XML.اسمحوا لي أن أعرف إذا كنت بحاجة إلى مزيد من المعلومات.

    public static void ImportKeyFromFile(string ContainerName, string inputFile)
    {
        try
        {
            // Create new XmlDocument.
            XmlDocument doc = new XmlDocument();

            // Load XML Document.
            doc.Load(inputFile);

            // Create the CspParameters object and set the key container 
            // name used to store the RSA key pair.
            CspParameters cp = new CspParameters();
            cp.KeyContainerName = ContainerName;

            // Create a new instance of RSACryptoServiceProvider that accesses
            // the key container MyKeyContainerName.
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);

            // Get RSA Parameters from xml document.
            rsa.FromXmlString(doc.InnerXml);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    public static void ExportKeyToFile(string ContainerName, string outputPath, bool private_key)
    {
        try
        {
            // Create the CspParameters object and set the key container 
            // name used to store the RSA key pair.
            CspParameters cp = new CspParameters();
            cp.KeyContainerName = ContainerName;

            // Create a new instance of RSACryptoServiceProvider that accesses
            // the key container MyKeyContainerName.
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);

            // Create new XmlDocument.
            XmlDocument doc = new XmlDocument();

            // Store rsa key.
            doc.InnerXml = rsa.ToXmlString(private_key);

            // Save Document.
            doc.Save(outputPath);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    public static Boolean VerifyXml(XmlDocument Doc, RSA Key)
    {
        // Check arguments. 
        if (Doc == null)
            throw new ArgumentException("Doc");
        if (Key == null)
            throw new ArgumentException("Key");

        // Create a new SignedXml object and pass it 
        // the XML document class.
        SignedXml signedXml = new SignedXml(Doc);

        // Find the "Signature" node and create a new 
        // XmlNodeList object.
        XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

        // Throw an exception if no signature was found. 
        if (nodeList.Count <= 0)
        {
            throw new CryptographicException("Verification failed: No Signature was found in the document.");
        }

        // Load the first <signature> node.  
        signedXml.LoadXml((XmlElement)nodeList[0]);

        // Check the signature and return the result. 
        return signedXml.CheckSignature(Key);
    }
    public static void SignXml(XmlDocument xmlDoc, RSA Key)
    {
        // Check arguments. 
        if (xmlDoc == null)
            throw new ArgumentException("xmlDoc");
        if (Key == null)
            throw new ArgumentException("Key");

        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(xmlDoc);

        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;

        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "";

        // Add an enveloped transformation to the reference.
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);

        // Add the reference to the SignedXml object.
        signedXml.AddReference(reference);

        // Compute the signature.
        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save 
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
    }
هل كانت مفيدة؟

المحلول

تكمن المشكلة في أنه لا يمكنك تخزين المفاتيح العامة في حاوية المفاتيح.للتحقق من التوقيع باستخدام مفتاح عام فقط، يجب عليك استيراد المفتاح من ملف XML باستخدام rsa.FromXmlString ثم قم بتمرير rsa مباشرة إلى وظيفة التحقق من التوقيع.إذا حاولت تخزين مفتاح عام في حاوية مفاتيح واسترجاعه لاحقًا، فسينتهي بك الأمر بإنشاء مفتاح جديد.كيفية تخزين مفتاح عام في حاوية مفتاح RSA على مستوى الجهاز

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top