Question

J'ai vu plusieurs questions similaires, mais aucune ne répond exactement à ce que je demande.

J'essaie de signer un XML puis de le vérifier avec la clé publique en utilisant C#.

Je signe le XML avec une clé puis j'exporte la clé vers un XML.Ensuite, apportez la clé et le XML signé sur un autre ordinateur, importez la clé en utilisant rsa.FromXmlString(doc.InnerXml), et vérifiez la signature XML.

Cela fonctionne si j'exporte les clés publiques et privées vers un XML en utilisant rsa.ToXmlString(True).Cependant, je souhaite exporter uniquement ma clé publique en utilisant rsa.ToXmlString(False).Si j'exporte uniquement la clé publique, que je l'importe sur le deuxième ordinateur et que j'essaie de valider la signature XML, cela indique que la signature n'est pas valide.

Premièrement, dois-je pouvoir vérifier le XML signé avec uniquement la clé publique ?

Deuxièmement, si cela est vrai, pourquoi ma fonction de vérification XML ne fonctionne-t-elle qu'avec la paire de clés pub/privée et pas uniquement avec la clé publique ?

Avez-vous une idée sur la façon de déboguer ce problème ?Je ne sais pas quoi faire d'autre parce que signedXml.CheckSignature(Key); ne fournit aucune information sur la raison de son échec.

Mes fonctions de clé d'importation, de clé d'exportation, de signature XML et de vérification XML sont ci-dessous.Faites-moi savoir si vous avez besoin de plus d'informations.

    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));
    }
Était-ce utile?

La solution

Le problème est que vous ne pouvez pas stocker de clés publiques dans un conteneur de clés.Pour vérifier une signature avec juste une clé publique, vous devez importer la clé depuis le XML en utilisant rsa.FromXmlString puis transmettez rsa directement à la fonction Vérifier la signature.Si vous essayez de stocker une clé publique dans un conteneur de clés et de la récupérer plus tard, vous finirez simplement par créer une nouvelle clé.Comment stocker une clé publique dans un conteneur de clé RSA au niveau de la machine

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top