SignedXml.CheckSignature gibt nur dann „true“ zurück, wenn ich die Überprüfung mit einem privaten Schlüssel durchführe

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

Frage

Ich habe mehrere ähnliche Fragen gesehen, aber keine, die genau auf meine Frage eingeht.

Ich versuche, ein XML zu signieren und es dann mit dem öffentlichen Schlüssel mithilfe von C# zu überprüfen.

Ich signiere das XML mit einem Schlüssel und exportiere den Schlüssel dann in ein XML.Nehmen Sie dann den Schlüssel und das signierte XML auf einen anderen Computer und importieren Sie den Schlüssel mit rsa.FromXmlString(doc.InnerXml), und überprüfen Sie die XML-Signatur.

Dies funktioniert, wenn ich sowohl den öffentlichen als auch den privaten Schlüssel in eine XML-Datei exportiere rsa.ToXmlString(True).Ich möchte jedoch nur meinen öffentlichen Schlüssel mit exportieren rsa.ToXmlString(False).Wenn ich nur den öffentlichen Schlüssel exportiere und ihn auf dem zweiten Computer importiere und versuche, die XML-Signatur zu validieren, wird mir angezeigt, dass die Signatur ungültig ist.

Erstens: Sollte ich in der Lage sein, das signierte XML nur mit dem öffentlichen Schlüssel zu überprüfen?

Zweitens: Wenn das wahr ist, warum funktioniert meine XML-Überprüfungsfunktion nur mit dem Pub/Privat-Schlüsselpaar und nicht nur mit dem öffentlichen Schlüssel?

Wissen Sie, wie Sie dieses Problem beheben können?Ich bin mir nicht sicher, was ich sonst tun soll, weil signedXml.CheckSignature(Key); gibt keine Auskunft darüber, warum es fehlgeschlagen ist.

Meine Importschlüssel-, Exportschlüssel-, XML-Signatur- und XML-Überprüfungsfunktionen sind unten aufgeführt.Lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

    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));
    }
War es hilfreich?

Lösung

Das Problem liegt darin, dass Sie öffentliche Schlüssel nicht in einem Schlüsselcontainer speichern können.Um eine Signatur nur mit einem öffentlichen Schlüssel zu überprüfen, sollten Sie den Schlüssel aus dem XML importieren mit rsa.FromXmlString Übergeben Sie dann rsa direkt an die Funktion „Signatur überprüfen“.Wenn Sie versuchen, einen öffentlichen Schlüssel in einem Schlüsselcontainer zu speichern und ihn später abzurufen, erstellen Sie am Ende einfach einen neuen Schlüssel.So speichern Sie einen öffentlichen Schlüssel in einem RSA-Schlüsselcontainer auf Maschinenebene

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top