Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SignedXml.CheckSignature仅在使用私钥验证时返回true_C#_Xml_Xml Signature_Xml Dsig - Fatal编程技术网

C# SignedXml.CheckSignature仅在使用私钥验证时返回true

C# SignedXml.CheckSignature仅在使用私钥验证时返回true,c#,xml,xml-signature,xml-dsig,C#,Xml,Xml Signature,Xml Dsig,我见过几个类似的问题,但没有一个能完全回答我的问题 我正在尝试对XML进行签名,然后使用C#用公钥验证它 我用密钥对XML进行签名,然后将密钥导出为XML。然后将密钥和签名的XML带到另一台计算机,使用rsa.FromXmlString(doc.InnerXml)导入密钥,并验证XML签名 如果我使用rsa.ToXmlString(True)将公钥和私钥导出到XML中,这一点就可以实现。但是,我只想使用rsa.ToXmlString(False)导出我的公钥。如果我只导出公钥,然后在第二台计算机

我见过几个类似的问题,但没有一个能完全回答我的问题

我正在尝试对XML进行签名,然后使用C#用公钥验证它

我用密钥对XML进行签名,然后将密钥导出为XML。然后将密钥和签名的XML带到另一台计算机,使用rsa.FromXmlString(doc.InnerXml)导入密钥,并验证XML签名

如果我使用
rsa.ToXmlString(True)
将公钥和私钥导出到XML中,这一点就可以实现。但是,我只想使用rsa.ToXmlString(False)导出我的公钥。如果我只导出公钥,然后在第二台计算机上导入它,并尝试验证XML签名,则表示该签名无效

首先,我应该只使用公钥验证签名的XML吗

第二,如果这是真的,为什么我的verify-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));
    }
公共静态void ImportKeyFromFile(string ContainerName,string inputFile)
{
尝试
{
//创建新的XML文档。
XmlDocument doc=新的XmlDocument();
//加载XML文档。
单据加载(输入文件);
//创建CspParameters对象并设置密钥容器
//用于存储RSA密钥对的名称。
CspParameters cp=新的CspParameters();
cp.KeyContainerName=容器名称;
//创建可访问的RSACryptServiceProvider的新实例
//密钥容器MyKeyContainerName。
RSACryptServiceProvider rsa=新的RSACryptServiceProvider(cp);
//从xml文档中获取RSA参数。
rsa.FromXmlString(doc.InnerXml);
}
捕获(例外情况除外)
{
MessageBox.Show(例如Message);
}
}
公共静态void ExportKeyToFile(字符串ContainerName、字符串outputPath、布尔私钥)
{
尝试
{
//创建CspParameters对象并设置密钥容器
//用于存储RSA密钥对的名称。
CspParameters cp=新的CspParameters();
cp.KeyContainerName=容器名称;
//创建可访问的RSACryptServiceProvider的新实例
//密钥容器MyKeyContainerName。
RSACryptServiceProvider rsa=新的RSACryptServiceProvider(cp);
//创建新的XML文档。
XmlDocument doc=新的XmlDocument();
//存储rsa密钥。
doc.InnerXml=rsa.ToXmlString(私钥);
//保存文档。
单据保存(outputPath);
}
捕获(例外情况除外)
{
MessageBox.Show(例如Message);
}
}
公共静态布尔验证XML(XmlDocument文档,RSA密钥)
{
//检查参数。
如果(Doc==null)
抛出新的ArgumentException(“Doc”);
if(Key==null)
抛出新的ArgumentException(“键”);
//创建一个新的SignedXml对象并传递它
//XML文档类。
SignedXml SignedXml=新的SignedXml(Doc);
//找到“签名”节点并创建一个新的
//XmlNodeList对象。
XmlNodeList nodeList=Doc.GetElementsByTagName(“签名”);
//如果未找到签名,则引发异常。

如果(nodeList.Count问题在于无法在密钥容器中存储公钥。若要仅使用公钥验证签名,应使用rsa从XML中导入密钥。FromXmlString
然后将rsa直接传递给验证签名函数。如果尝试在密钥容器中存储公钥并稍后检索它,则我将创建一个新的密钥。

另一个选项是包含密钥(甚至证书)在签名文档中。这不会占用太多空间,但可以让消费者从单独的渠道获取密钥。消费者仍需要检查公钥是否属于她认为的人。在我的例子中,消费者在接收xml时已经拥有公钥。是的,但他们只需要一个密钥指纹(密钥散列)与接收到的密钥进行比较。