Pregunta

He visto varias preguntas similares, pero ninguna aborda exactamente lo que estoy preguntando.

Estoy intentando firmar un XML y luego verificarlo con la clave pública usando C#.

Firmo el XML con una clave y luego exporto la clave a un XML.Luego lleve la clave y el XML firmado a una computadora diferente, importe la clave usando rsa.FromXmlString(doc.InnerXml), y verifique la firma XML.

Esto funciona si exporto las claves pública y privada a un XML usando rsa.ToXmlString(True).Sin embargo, quiero exportar solo mi clave pública usando rsa.ToXmlString(False).Si exporto solo la clave pública y la importo en la segunda computadora e intento validar la firma XML, dice que la firma no es válida.

Primero, ¿debería poder verificar el XML firmado solo con la clave pública?

En segundo lugar, si eso es cierto, ¿por qué mi función de verificación XML solo funciona con el par de claves pub/priv y no solo con la clave pública?

¿Tiene alguna sabiduría sobre cómo solucionar este problema?No estoy seguro de qué más hacer porque signedXml.CheckSignature(Key); no proporciona ninguna información sobre por qué falló.

Mi clave de importación, clave de exportación, firma XML y funciones de verificación XML se encuentran a continuación.Déjeme saber si usted necesita más información.

    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));
    }
¿Fue útil?

Solución

El problema es porque no puede almacenar las llaves públicas en un contenedor clave.Para verificar una firma con solo una clave pública, debe importar la tecla desde el XML utilizando rsa.FromXmlString, luego pase RSA directamente a la función Verificar firma.Si intenta almacenar una clave pública en un contenedor clave y recuperarlo más tarde, terminará creando una nueva clave. Cómo almacenar una clave públicaEn un contenedor de teclas RSA de nivel de máquina

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top