C# SignedXml.CheckSignature在.NET 4中失败,但在.NET 3.5、3或2中有效
我收到了第三方网络服务的回复。我加载带有该响应的XmlDocumentC# SignedXml.CheckSignature在.NET 4中失败,但在.NET 3.5、3或2中有效,c#,security,certificate,signature,signedxml,C#,Security,Certificate,Signature,Signedxml,我收到了第三方网络服务的回复。我加载带有该响应的XmlDocument string txt = readStream.ReadToEnd(); response = new XmlDocument(); response.PreserveWhitespace = true; response.LoadXml(txt); return response; 现在我想验证响应是否使用证书签名。我有一个VerifyXmlDoc(xmldocumentxmldoc)方法,我在
string txt = readStream.ReadToEnd();
response = new XmlDocument();
response.PreserveWhitespace = true;
response.LoadXml(txt);
return response;
现在我想验证响应是否使用证书签名。我有一个VerifyXmlDoc(xmldocumentxmldoc)
方法,我在上找到了这个方法
我知道这个消息是正确的
public bool VerifyXmlDoc(XmlDocument xmlDoc)
{
SignedXml signed = new SignedXml(xmlDoc);
XmlNodeList signatureNodeList = xmlDoc.GetElementsByTagName("Signature");
signed.LoadXml((XmlElement)signatureNodeList[0]);
X509Certificate2 serviceCertificate = null;
foreach (KeyInfoClause clause in signed.KeyInfo)
{
if (clause is KeyInfoX509Data)
{
if (((KeyInfoX509Data)clause).Certificates.Count > 0)
{
serviceCertificate = (X509Certificate2)((KeyInfoX509Data)clause).Certificates[0];
}
}
}
bool result = signed.CheckSignature(serviceCertificate, true);
return result;
}
若我将项目的目标框架设置为.NET3.5或.NET3或.NET2,那个么效果很好。结果是真的。但若我将目标框架更改为.NET4,结果将是错误的。
(我必须使用.NET4)
关于如何解决这个问题有什么想法吗?尝试显式地为SignedXml类的SignedInfo属性设置规范化方法。。在.Net 2.0和.Net 4.0之间,这里的默认行为似乎发生了变化
signed.SignedInfo.CanonicalizationMethod = Signed.XmlDsigExcC14NTransformUrl;
参考:
从.NET framework 4/4.5中,用于x509证书和其他安全功能的类位于System.IdentityModel.dll中。在提到的名称空间中搜索相应的类。这是一个已知问题。.NET3.5和.NET4.0之间的规范化实现已更改 我不知道这是否适用于所有的XML签名,但通过我所做的测试,下面的工作是有效的 将以下C14N转换类添加到项目中:
公共类MyXmlDsigC14NTransform:XmlDsigC14NTransform{
静态XmlDocument\u文档;
公共静态XML文档{
设置{
_文件=价值;
}
}
公共MyXmlDsigC14NTransform(){}
公共重写对象GetOutput(){
返回base.GetOutput();
}
公共覆盖无效LoadInnerXml(XmlNodeList nodeList){
LoadInnerXml(节点列表);
}
受保护的重写XmlNodeList GetInnerXml(){
XmlNodeList nodeList=base.GetInnerXml();
返回节点列表;
}
公共XmlElement GetXml(){
返回base.GetXml();
}
公共覆盖无效加载输入(对象obj){
int n;
bool fDefaultNS=真;
xmlement元素=((XmlDocument)obj).DocumentElement;
if(element.Name.Contains(“SignedInfo”)){
XmlNodeList DigestValue=element.GetElementsByTagName(“DigestValue”,element.NamespaceURI);
字符串strHash=DigestValue[0]。InnerText;
XmlNodeList nodeList=\u document.GetElementsByTagName(element.Name);
对于(n=0;n }
我解决了这个问题,将相同的名称空间从签名标记添加到SignedInfo。
像这样:
之前:
之后:
为了检查NET 4.0+上的签名,您必须更改规范化方法的上下文,因此必须按以下方式初始化signedXml对象:
XmlNodeList signatureNodeList = xmlDoc.GetElementsByTagName("Signature");
SignedXml signedXml = new SignedXml((XmlElement)signatureNodeList[0]);
signedXml.LoadXml((XmlElement)signatureNodeList[0]);
//Then you proceed your check as usual
我也有同样的问题,但这些答案对我都没有帮助。在这种情况下,它是否工作取决于我使用的操作系统,而不是.Net版本 我已通过在app.config中添加以下代码来启用SignedXML日志,以查看后面发生的情况:
<system.diagnostics>
<sources>
<source name="System.Security.Cryptography.Xml.SignedXml" switchName="XmlDsigLogSwitch">
<listeners>
<add name="logFile" />
</listeners>
</source>
</sources>
<switches>
<add name="XmlDsigLogSwitch" value="Verbose" />
</switches>
<sharedListeners>
<add name="logFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="XmlDsigLog.txt"/>
</sharedListeners>
<trace autoflush="true">
<listeners>
<add name="logFile" />
</listeners>
</trace>
</system.diagnostics>
我发现这篇Microsoft支持文章试图修复安全更新3141780引入的错误:
在那篇文章中,在场景2部分中,有两种解决方案,我修复了应用与XPath转换方法相关的注册表项的问题:
HKEY\U本地\U计算机\软件\ Microsoft.NETFramework\Security\SafeTransformMethods@XmlDsigXPathTransform=您可能会在一个类似的问题中找到帮助:使用什么算法对其进行签名?您好,您可以发布异常调用堆栈吗?如果我读对了,如果你还在寻找的话,我想可能有解决问题的方法。也许通过.Net源代码调试也会给你一个提示。您可以在VisualStudio中的某个地方/以某种方式启用它:但是规范化方法是一个字符串。尝试了这个,没有任何区别(.NET 3.5 reading.NET 4.0 generated Signature)为什么_文档变量是静态的?
XmlNodeList signatureNodeList = xmlDoc.GetElementsByTagName("Signature");
SignedXml signedXml = new SignedXml((XmlElement)signatureNodeList[0]);
signedXml.LoadXml((XmlElement)signatureNodeList[0]);
//Then you proceed your check as usual
<system.diagnostics>
<sources>
<source name="System.Security.Cryptography.Xml.SignedXml" switchName="XmlDsigLogSwitch">
<listeners>
<add name="logFile" />
</listeners>
</source>
</sources>
<switches>
<add name="XmlDsigLogSwitch" value="Verbose" />
</switches>
<sharedListeners>
<add name="logFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="XmlDsigLog.txt"/>
</sharedListeners>
<trace autoflush="true">
<listeners>
<add name="logFile" />
</listeners>
</trace>
</system.diagnostics>
System.Security.Cryptography.Xml.SignedXml Information: 17 : [SignedXml#033ec00f, UnsafeTransformMethod] Canonicalization method "http://www.w3.org/TR/1999/REC-xpath-19991116" is not on the safe list. Safe canonicalization methods are: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments", "http://www.w3.org/2001/10/xml-exc-c14n#", "http://www.w3.org/2001/10/xml-exc-c14n#WithComments", "http://www.w3.org/2000/09/xmldsig#enveloped-signature", "http://www.w3.org/2000/09/xmldsig#base64", "urn:mpeg:mpeg21:2003:01-REL-R-NS:licenseTransform", "http://www.w3.org/2002/07/decrypt#XML".