当尝试在C#中使用SignedXml签署xml请求时,我能够生成签名和签名的xml请求,但是当我发送此消息时,我收到来自我的webservice的失败消息。错误说明:数据和摘要值不匹配。
深入挖掘,我检查了我们用Java开发的等效代码。生成代码的xml签名请求与我的C#代码生成的摘要值不同,Java代码从Web服务获取成功消息。
在使用我的网络服务提供的测试工具进行了大量讨论和分析之后,我们理解这一点:摘要值会根据您在使用ComputeSignature()之前在请求中指定数字签名位置的位置而更改。但是我无法找到在计算签名之前指定位置的方法。这是我的代码:
/*=================*/
//CODE to remove whitespaces from the xml before building the xmlDocument
String thisLine = "";
String xmlString = "";
StreamReader br = new StreamReader(Server.MapPath("~/" + fp));
while ((thisLine = br.ReadLine()) != null)
{
xmlString = xmlString + thisLine.Trim();
}
br.Close();
Debug.WriteLine("new logic: " + xmlString);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xmlString);
/*================*/
SignedXml signedXml = new SignedXml(xmlDocument);
//XmlDsigExcC14NTransformUrl
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl;
signedXml.SigningKey = cert.PrivateKey;
signedXml.KeyInfo.AddClause(new System.Security.Cryptography.Xml.KeyInfoX509Data(cert));
Reference tRef = new Reference("");
/*
XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
//Transform transf = new XmlDsigEnvelopedSignatureTransform(false);
tRef.AddTransform(transf);
*/
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
tRef.AddTransform(env);
signedXml.AddReference(tRef);
signedXml.ComputeSignature();
XmlElement xmlDsig = signedXml.GetXml();
xmlDsig.SetAttribute("Id", "Signature-1");
XmlElement rootNode = xmlDocument.DocumentElement;
rootNode.AppendChild(xmlDsig);
XmlTextWriter w = new XmlTextWriter(Server.MapPath("~/attrdigsig2.xml"), new UTF8Encoding(false));
w.Formatting = Formatting.Indented;
xmlDocument.WriteTo(w);
w.Close();
以下是我收到的签名请求:
<?xml version="1.0" encoding="utf-8"?>
<ns:User xmlns:ns="http://www.user.com">
<ns:Username>1DDOagUser</ns:Username>
<ns:Password>toyota12</ns:Password>
<Signature Id="Signature-1" xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>KEqvZWvpT3yYqMMJSTBmUKNIQw4=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>YQ+81KnxwM9RibFpmS48Gbfdv7gBxgXrH6XWdoF+OZaUq+uJOOcuuC9KNmC4pkMs0V/LEw2WI6zjs9ML8kxAx3vcU/8jZ9/b8Z1EK7ndCcqDvkfBUpltHQy9FyP3AQyeFyK0SFvcyJCxvetc7uoJgYDvKUVU/ydqolw2ZbOXCHvN34SwbqGgGlBed++I7yk7KWIOWXsfjdSVwkuIyvEuVwxCmHHhxgjjfVaPnJMBY3D1Ali28d+rwKphT3dXdroEjXIedIK6lkrNOlHsaWZGYgJxNN08nN8bnNCe9QXapzHysSLnc3tkbJ1i2KjVHpLxwDfxFuuhWxh2sCKCoNvLgA==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIC0TCCAbmgAwIBAgIGATDa3Nm5MA0GCSqGSIb3DQEBBQUAMBgxFjAUBgNVBAMTDVNPQVBCb3hDb25maWcwHhcNMDgwNjE4MTAyODAwWhcNMjEwNjE4MTAyODAwWjAYMRYwFAYDVQQDEw1TT0FQQm94Q29uZmlnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApLw4QAWqVmEr+CEo8Fp8WPq9Oo7BdnNOtMT5sUp0IN4NVvKmdI8ju3HsbnXzI7csNDzK6Feo19J/XLZk/Lr3Q4bLmmD+bMLFljiIgQ89+Bwc3mtyT1Rr4WBQUKnF8+8y65m2RebySelzgWIeZM72JoThSw85VBtyHvjlQnTAnfwX0NV7mH+kbQDi0c4Q4UZhKWFfb5L2tbjcknsG0k4De07qIw+RsGipkuNoFyI6BwwC0IERv48sacL30nWAOZMNDkm4S61aAYuzfMZySzPseU6BUdIdYAnITgj4tHRJZ93OYnn6LObEkYxobyGi6SULtBQQYzHKgeeyvru2Z1L7nQIDAQABoyEwHzAdBgNVHQ4EFgQUjq3/y0NF+tlUqwLc8SP4uV4/PK4wDQYJKoZIhvcNAQEFBQADggEBAAJvxTw5cc/32ahQ2TlBCrBNeHvji4QYItimkoqQa1EMyBSnx1FXNRyfJ9Da/20ZdIvIfJvIozIU0V/iFd7Hi+a2bZeMkN/ofvUh3QchHfkP/718JhcIvug3fctUX27ENHLRRU/rzMvKg40+H9BJoos6lu7qgAyayCRgKR5A/U3cSE9ZrYMGBNqy/mSIscZXhDJw0KATLHircXwRjpN+0lk+7/df5T8tc8wJOIvETCfDaQlDzXHw4jhQFydloMY4Tm4//VZTVVh1nzt2rVv52pHZGP8Shb9e5qS/QicBTVqysyVQEpYktRrrTwZcbq/65sV0lOao2JzZOuj3qvdJ4kw=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</ns:User>
我得到的摘要值:KEqvZWvpT3yYqMMJSTBmUKNIQw4=
更正摘要值(由Java代码生成并从Web服务获得成功响应的值):aa4phJzO4YWc2ZQ1CG8HZ4cB1SA=
备注:要签名的xml是普通的xml而不是SOAP xml请求。我对SOAP xml请求使用了相同的签名逻辑,并且Web服务接受了它生成的响应(Web服务包含以下两种方法:1表示正常的xml请求,1表示soap xml请求)。
答案 0 :(得分:0)
我想出了这个问题。它与将签名请求发送到Web服务URL时保留空白有关。因此,如果您不添加PreserveWhitespace = true语句,则发送给验证程序的数据与签名的数据基本不同(因为它不包含空格)。因此,获得了不同的散列值,导致无效的签名错误。
以下是代码段:
XmlDocument xpdoc = new XmlDocument { PreserveWhitespace = true };
xpdoc.Load(@fpath);
using (Stream stream = webRequest.GetRequestStream())
{
xpdoc.Save(stream); //writes the request body into the http web request stream
}
有人可以帮助我将答案标记为已解决或已关闭吗?谢谢。