C# ComputeSignature和手动生成的哈希是不同的
我正在创建带有数字签名的请求xml。下面是我的代码C# ComputeSignature和手动生成的哈希是不同的,c#,xml,cryptography,digital-signature,sha256,C#,Xml,Cryptography,Digital Signature,Sha256,我正在创建带有数字签名的请求xml。下面是我的代码 CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); var exportedKeyMaterial = cert.PrivateKey.ToXmlString( /* includePrivateParameters = */ tru
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
var exportedKeyMaterial = cert.PrivateKey.ToXmlString( /* includePrivateParameters = */ true);
var key = new RSACryptoServiceProvider(new CspParameters(24 /* PROV_RSA_AES */));
key.PersistKeyInCsp = false;
key.FromXmlString(exportedKeyMaterial);
string tokenId = string.Format("X509-{0}", Guid.NewGuid());
string signatureId = string.Format("SIG-{0}", Guid.NewGuid());
string tokenRefId = string.Format("STR-{0}", Guid.NewGuid());
string kiId = string.Format("KI-{0}", Guid.NewGuid());
string bodyId = string.Format("id-{0}", Guid.NewGuid());
XmlNamespaceManager ns = new XmlNamespaceManager(xmlDoc.NameTable);
ns.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
ns.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
ns.AddNamespace("wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing");
ns.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
XmlElement body = xmlDoc.DocumentElement.SelectSingleNode(@"//soapenv:Body", ns) as XmlElement;
if (body == null)
throw new ApplicationException("No body tag found");
body.SetAttribute("id", bodyId);
SignedXml signedXml = new SignedXml(body);
signedXml.Signature.Id = signatureId;
signedXml.SigningKey = key;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
KeyInfo keyInfo = new KeyInfo();
keyInfo.Id = kiId;
SecurityTokenReference tokenRef = new SecurityTokenReference();
tokenRef.ValueType = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3";
tokenRef.RelativeReference = tokenId;
tokenRef.Id = tokenRefId;
// Add Security Token reference
keyInfo.AddClause(tokenRef);
signedXml.KeyInfo = keyInfo;
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
XmlDsigExcC14NTransform canMethod = (XmlDsigExcC14NTransform)signedXml.SignedInfo.CanonicalizationMethodObject;
canMethod.InclusiveNamespacesPrefixList = "soap";
Reference reference = new Reference();
reference.Uri = string.Format("#{0}", bodyId);
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
reference.AddTransform(new Microsoft.Web.Services3.Security.Xml.XmlDsigExcC14NTransform());
signedXml.AddReference(reference);
signedXml.ComputeSignature();
XmlElement signedElement = signedXml.GetXml();
string hash = CalculateDigestOfBody(body);
public string CalculateDigestOfBody(XmlElement xmlDoc)
{
SHA256 algo = new SHA256CryptoServiceProvider();
byte[] byteHash = algo.ComputeHash(Encoding.UTF8.GetBytes(xmlDoc.OuterXml));
string hashString = Convert.ToBase64String(byteHash);
return hashString;
}
这将生成下面的soap头
<Signature Id="SIG-44779d9b-7d39-4c27-877b-a6de1d9365fc" xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="soap" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
</CanonicalizationMethod>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#id-98b3d734-ee46-49bb-aee8-c151d41defe5">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>..</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>..</SignatureValue>
..
..
当我比较ComputeSignature和手动计算的哈希/摘要的摘要值时,它们并不相等
根据我的理解,它们应该是相等的,因为两者都是在身体上计算的
我在这里遗漏了什么。对于那些对答案感兴趣的人: 一旦调用ComputeSignature方法,就不要更改主体或已签名的信息元素。另外,尽量不要手动更改soap:header子项中的任何内容 下面是我做错的代码。评论这是完美的作品
signedElement.Prefix = "ds";
signedElement.FirstChild.Prefix = "ds";
signedElement.FirstChild.FirstChild.Prefix = "ds";
我在ComputeSignature下面添加了这些行。在那之后,我试图手动计算摘要。因此,这两个摘要永远无法匹配
摘要输入中的任何更改都将更改摘要。您必须使用XmlDocument吗?使用LINQtoXML,命名空间处理非常简单。顺便说一句,您介意将输出重新格式化为多行吗?这真的很难理解为一条长长的线。(如果你愿意,我很乐意为你做这件事,但没有你的允许,我不想做。)@DaisyShipton我已经做了格式化。我可以使用LINQtoXML,但同样,主要关注的是如何使InclusiveNamespaces使用前缀。我不想通过遍历xml以编程的方式实现。我认为应该有一种在CanonicalizationObject中设置它的方法。现在我们可以看到XML了,你问的问题更清楚了——但我不清楚为什么。看起来,
InclusiveNamespaces
只是位于不同的名称空间URI中,我怀疑它是故意位于不同的名称空间URI中的。鉴于这是一个指定其名称空间的框架类型,您能否提供更多的上下文,说明为什么您认为它应该与签名位于同一名称空间中?您谈论的是“歧义错误”-您能给出问题中的确切错误吗?问题是Signature元素用一些URI定义了xmlns。现在,由于这个名称空间是在没有任何前缀的情况下创建的,它将被所有子元素继承,因此InclusiveNamespaces元素也将继承它。但InclusiveNamespaces本身正在创建具有不同URI的XMLN。因此,框架无法识别它应该接受的URI。你所说的“不能识别它应该接受的URI”是什么意思?这意味着InclusiveNamespaces元素位于不同的名称空间URI中。它没有什么不明确的地方——它只是在一个不同的名称空间中。