我正在使用数字签名创建请求xml。以下是我的代码。
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的摘要值和手动计算的散列/摘要时,它们不相等。
根据我的理解,他们应该是平等的,因为两者都是按身体计算的。
我在这里缺少什么。
答案 0 :(得分:0)
对于那些对答案感兴趣的人:
调用ComputeSignature方法后,切勿更改正文或签名信息元素。另外,尽量不要在soap的子代中更改任何内容:手动添加标题。
以下是我做错的代码。评论完美无缺。
signedElement.Prefix = "ds";
signedElement.FirstChild.Prefix = "ds";
signedElement.FirstChild.FirstChild.Prefix = "ds";
我在ComputeSignature下面添加了这些行。之后我试图手动计算摘要。因此,两个摘要都无法匹配。
消化输入的任何变化都会改变摘要。