2

我见过几个类似的问题,但没有一个能完全解决我的问题。

我正在尝试对 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));
    }
4

1 回答 1

1

问题是因为您不能将公钥存储在密钥容器中。要仅使用公钥验证签名,您应该使用从 XML 导入密钥,rsa.FromXmlString然后将 rsa 直接传递给验证签名函数。如果您尝试将公钥存储在密钥容器中并稍后检索它,您最终将创建一个新密钥。 如何将公钥存储在机器级 RSA 密钥容器中

于 2014-01-09T17:33:14.660 回答