长话短说,我可以签好文件。但每次验证它们都会返回false。我查看了google的前5或6页并找到了解决方案,但我发现的每个“修复”都无法提供帮助。任何帮助将不胜感激,因为我一直试图解决这个问题一个多星期了。此外,这些证书的私钥不可导出,也不能导出。我不确定这是否重要。此外,我现在选择不包括ValidateCertificate,因为它从来没有一次成功。它总是在CheckSignature()失败。谢谢。
我正在使用它来生成我的证书:
makecert -a SHA256 -n“CN = JEA2.me”-pe -r -len 2048 -sy 24 -sky signature -sv jeame2.pvk jeame2.cer
certmgr / add jeame2.cer / s / r localmachine root
makecert -sk“jea2.me”-iv jeame2.pvk -n“CN = JEA2IIS.me”-eku 1.3.6.1.4.1.311.10.3.12 -pe -sy 24 -ss my -sr localmachine -len 2048 -sky签名-ic Jeame2.cer IIS-ServerCert-Jeame2.cer
从这里我将它们直接安装到本地机器中 - >受信任的根证书颁发机构
private static X509Certificate2 CheckXmldsigSignature(XmlDocument document)
{
X509Certificate2 certificate = null;
try
{
XmlNodeList nodeList = document.GetElementsByTagName("Signature", Xmldsigns);
if (nodeList.Count != 1)
{
Logger.ErrorFormat("Found {0} signature elements in file", nodeList.Count);
throw new InvalidOperationException(
"The XML document must have a single element with local name: \"Signature\" and namespace URI: " + Xmldsigns);
}
else
{
Logger.DebugFormat("Found Signature element successfully");
}
RSAPKCS1SHA256SignatureDescription.Register();
var signatureElement = (XmlElement)nodeList[0];
var signedXml = new SignedXml(document);
signedXml.LoadXml(signatureElement);
var keyInfoX509 =
(KeyInfoX509Data)
(from KeyInfoClause kic in signedXml.KeyInfo where kic is KeyInfoX509Data select kic).Single();
if (keyInfoX509.Certificates.Count != 1)
{
var msg = "The signature must contain information for one certificate.";
Logger.Error(msg);
throw new InvalidOperationException(msg);
}
else
{
Logger.DebugFormat("Extracted X509 certificate data successfully");
}
certificate = (X509Certificate2)keyInfoX509.Certificates[0];
bool validSignature = signedXml.CheckSignature(); //was null parameters. This too does not work.
if (!validSignature)
{
var msg = " SignedXml.CheckSignature returned false.";
throw new InvalidOperationException(msg);
}
else
{
Logger.DebugFormat("SignedXml.CheckSignature returned true.");
}
}
catch (Exception ex)
{
ScriptPro.Common.Logging.LogEx.LogException(Logger, ex);
throw;
}
return certificate;
}
private static Stream SignSHA256Stream(X509Certificate2 certificate, Stream stream)
{
if (certificate == null)
{
Logger.Error("certificate argument is null");
throw new ArgumentNullException("certificate");
}
if (stream == null)
{
Logger.Error("stream argument is null");
throw new ArgumentNullException("stream");
}
RSAPKCS1SHA256SignatureDescription.Register();
var document = new XmlDocument();
document.PreserveWhitespace = true; // May not be necessary.
document.Load(stream);
XmlNode root = document.DocumentElement;
XmlNodeList nodeList = document.GetElementsByTagName("Signature", Xmldsigns);
while (nodeList.Count > 0)
{
root.RemoveChild(nodeList[0]);
}
Reference reference = new Reference(string.Empty);
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
CspParameters csp = new CspParameters(24);
csp.Flags = CspProviderFlags.UseMachineKeyStore;
csp.KeyContainerName = "XML_DISG_RSA_KEY";
RSACryptoServiceProvider key = new RSACryptoServiceProvider(csp);
key.PersistKeyInCsp = false;
var keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(certificate));
SignedXml sxml = new SignedXml(document);
sxml.KeyInfo = keyInfo;
sxml.SigningKey = key;
sxml.SignedInfo.SignatureMethod = Xmldsigns256;
sxml.AddReference(reference);
sxml.ComputeSignature();
XmlElement xmlDigitalSignature = sxml.GetXml();
if (document.DocumentElement == null)
{
document.AppendChild(document.ImportNode(xmlDigitalSignature, true));
}
else
{
document.DocumentElement.AppendChild(document.ImportNode(xmlDigitalSignature, true));
}
if (document.FirstChild is XmlDeclaration)
{
document.RemoveChild(document.FirstChild);
}
MemoryStream outStream = new MemoryStream();
document.Save(outStream);
return outStream;
}
private static void SignSHA256File(X509Certificate2 certificate, FileInfo file)
{
if (certificate == null)
{
Logger.Error("certificate argument is null");
throw new ArgumentNullException("certificate");
}
if (file == null)
{
Logger.Error("file argument is null");
throw new ArgumentNullException("file");
}
if (!file.Exists)
{
Logger.ErrorFormat("File {0} does not exist.", file.Name);
throw new ArgumentException("File must exist.", "file");
}
if (file.IsReadOnly)
{
Logger.ErrorFormat("File {0} is read only.", file.Name);
throw new ArgumentException("File is read only.", "file");
}
FileStream stream = file.OpenRead();
string s = string.Empty;
using (StreamReader reader = new StreamReader(stream))
{
s = reader.ReadToEnd();
}
MemoryStream stream2 = new MemoryStream(Encoding.Default.GetBytes(s));
Stream inStream = SignSHA256Stream(certificate, stream2);
XmlDocument document = new XmlDocument();
inStream.Seek(0L, SeekOrigin.Begin);
document.Load(inStream);
Logger.InfoFormat("Saving {0}", file.FullName);
document.Save(file.FullName);
}
public class RSAPKCS1SHA256SignatureDescription : SignatureDescription
{
private const int PROV_RSA_AES = 24;
public RSAPKCS1SHA256SignatureDescription()
{
this.KeyAlgorithm = "System.Security.Cryptography.RSACryptoServiceProvider";
this.DigestAlgorithm = "System.Security.Cryptography.SHA256CryptoServiceProvider"; // use System.Security.Cryptography.SHA256Managed for .NET 4.5
this.FormatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureFormatter";
this.DeformatterAlgorithm = "System.Security.Cryptography.RSAPKCS1SignatureDeformatter";
}
public static void Register()
{
CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
}
public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
var asymmetricSignatureDeformatter = (AsymmetricSignatureDeformatter)CryptoConfig.CreateFromName(DeformatterAlgorithm);
asymmetricSignatureDeformatter.SetKey(key);
asymmetricSignatureDeformatter.SetHashAlgorithm("SHA256");
return asymmetricSignatureDeformatter;
}
public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
var asymmetricSignatureFormatter = (AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
asymmetricSignatureFormatter.SetKey(key);
asymmetricSignatureFormatter.SetHashAlgorithm("SHA256");
return asymmetricSignatureFormatter;
}
}
}
以下是我的两个XML文件: 1.XML:
<node1>
<node2>
</node2>
<Signature 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/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>3nIr0blku+Nsu3FgibCxfQRGBtSmtZL4JGodmaU8blE= </DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>O3ihm7QwE/vh9VZ6CtdENAhB9Ve8jceATCgdJuaQkUHpPWxrG01TftUlrw9a/dQGfW48jJMPngwgcfqnbFspmEEGsBe1xoWQd6mdy2wVRBcQSjqdReNNzs0uQz3/1wPPk4Y2UO+fL+CVNzkIcMpne+t80c2eU4cHBa1WyL5qSlc=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIICFDCCAX2gAwIBAgIQ2rStbEE1JJhHRLiuA4n/0jANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDEwtKQUxDT1JOLm1lMjAeFw0xNjAzMzAxODE1MDFaFw0zOTEyMzEyMzU5NTlaMBkxFzAVBgNVBAMTDkpBTENPUk5JSVMubWUyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLJEzyRjaHLfK6zrg1Xdx2yO34d5sbd7ajFFVmb3zPKtVGmuJlCBPsDTC84pzHBTywVVApi3U2UwtuCh96rQu5r3nYUT/E46CtexWiFATyh0M9+wD/h3hZj1CQ0YHTEZWznOWWIdbNRAcp99tGSALrwjH2rEJhGHHpVn7otCNmZQIDAQABo2AwXjATBgNVHSUEDDAKBggrBgEFBQcDATBHBgNVHQEEQDA+gBAgVyu7w3c59jEjiSh/vma+oRgwFjEUMBIGA1UEAxMLSkFMQ09STi5tZTKCEFvqkxy0Sd+mSgbqvsCEqKcwDQYJKoZIhvcNAQELBQADgYEAAcM6GlR3UpjIY4TWWuMiSyqiUiAGgg3JetiUXj1EVZ7TZVvyoVA1L/wd8ZHt+nZu1UtJmJ8sU7eu55TMVcX/xu7QoYsp6JtbPp5abLI6rnOCwDfyorrjM4S8Rm2RCO3PhL0NC9i9QBPfNV15FEbFpeqHZGw/xmyGzEv3EWxEESE=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</node1>
2.XML:
<metadata>
<Signature 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/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>wc+6kgUoF9TE7KL1OQXm0EzAIYZuVVc6w3zOKsIY8yU= </DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>MDJn2QLG65LChsJOAN9zKmq4Br5JFSncaTMOmmsmL+DY4xcZt7e4VfI6/IehBkBUzDLeUJHWoE9sp7tVmArBiq/ZFm/ScB2/SRAAD+/NS0XxnxTPjvwu0JsmupNFJ364r/k31TYhI6TBmiCBIdZ6/3qV8LNPtS0iVrMkyhFw6L8=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIICFDCCAX2gAwIBAgIQ2rStbEE1JJhHRLiuA4n/0jANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDEwtKQUxDT1JOLm1lMjAeFw0xNjAzMzAxODE1MDFaFw0zOTEyMzEyMzU5NTlaMBkxFzAVBgNVBAMTDkpBTENPUk5JSVMubWUyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLJEzyRjaHLfK6zrg1Xdx2yO34d5sbd7ajFFVmb3zPKtVGmuJlCBPsDTC84pzHBTywVVApi3U2UwtuCh96rQu5r3nYUT/E46CtexWiFATyh0M9+wD/h3hZj1CQ0YHTEZWznOWWIdbNRAcp99tGSALrwjH2rEJhGHHpVn7otCNmZQIDAQABo2AwXjATBgNVHSUEDDAKBggrBgEFBQcDATBHBgNVHQEEQDA+gBAgVyu7w3c59jEjiSh/vma+oRgwFjEUMBIGA1UEAxMLSkFMQ09STi5tZTKCEFvqkxy0Sd+mSgbqvsCEqKcwDQYJKoZIhvcNAQELBQADgYEAAcM6GlR3UpjIY4TWWuMiSyqiUiAGgg3JetiUXj1EVZ7TZVvyoVA1L/wd8ZHt+nZu1UtJmJ8sU7eu55TMVcX/xu7QoYsp6JtbPp5abLI6rnOCwDfyorrjM4S8Rm2RCO3PhL0NC9i9QBPfNV15FEbFpeqHZGw/xmyGzEv3EWxEESE=</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</metadata>
public static bool VerifyXmldsigSignature(FileInfo file, bool useSHA256 = false)
{
Logger.InfoFormat("Checking Digital Signature and Certificate on {0}", file.FullName);
bool validCertificate = false;
if (file == null)
{
Logger.Error("file argument is null");
throw new ArgumentNullException("file");
}
if (!file.Exists)
{
Logger.ErrorFormat("File {0} does not exist.", file.Name);
throw new ArgumentException("File must exist.", "file");
}
try
{
var document = new XmlDocument();
document.PreserveWhitespace = true; document.Load(file.FullName);
DateTime timestamp = DateTime.UtcNow;
bool respectCertExpiration = HasTimestamp(document);
if (respectCertExpiration)
{
timestamp = CheckXadesTimestamp(document);
}
var certificate = CheckXmldsigSignature(document);
validCertificate = ValidateCertificate(certificate, timestamp, respectCertExpiration);
Logger.InfoFormat("Digital Signature and Certificate passed verification on {0}", file.FullName);
}
catch (Exception ex)
{
string message = string.Format("{0} failed signature verification.", file.FullName);
throw;
}
答案 0 :(得分:2)
查看代码,我可以找到两个可能存在问题的地方:
使用不带任何参数的CheckSignature()
要求签名证书由受信任的根颁发机构签名。由于您已经提取了作为签名一部分的证书,我建议您进行测试,将呼叫更改为
bool validSignature = signedXml.CheckSignature(certificate);
请注意,您只知道Xml是由文件中的证书信息签名的。您无法确认签名实际上是由任何特定方完成的。我假设你在调用函数中这样做,因为它返回证书。
在签名例程中,您设置了PreserveWhitespace=true
。这意味着空格将包含在签名的哈希计算中。确保在加载文档进行验证时设置PreserveWhitespace=true
(该部分未包含在发布的代码中,因此我不知道)。
最后,您的代码很容易受到Xml签名包装攻击,因为您没有正确检查签名的引用。有关示例,请参阅this blog post of mine。
答案 1 :(得分:0)
安德斯,谢谢你的建议。经过几周的努力,我终于得到了我的代码验证,我终于得到了一些工作,所以我想与你们分享。验证方法没有改变,Xade的东西是自定义的,不需要验证用我的代码签名的文件。最后,我使用以下2个网址作为我的起点,但谷歌的几十页也有所帮助:
https://blogs.msdn.microsoft.com/winsdk/2015/11/14/using-sha256-with-the-signedxml-class/ https://gist.github.com/sneal/f35de432115b840c4c1f#file-rsapkcs1sha256signaturedescription
private static Stream SignSHA256Stream(X509Certificate2 certificate, Stream stream)
{
if (certificate == null)
{
Logger.Error("certificate argument is null");
throw new ArgumentNullException("certificate");
}
if (stream == null)
{
Logger.Error("stream argument is null");
throw new ArgumentNullException("stream");
}
RSAPKCS1SHA256SignatureDescription.Register();
var document = new XmlDocument();
document.Load(stream);
XmlNode root = document.DocumentElement;
XmlNodeList nodeList = document.GetElementsByTagName("Signature", Xmldsigns);
// nodeList is actively updated so we delete element [0] until there are none left.
while (nodeList.Count > 0)
{
root.RemoveChild(nodeList[0]);
}
Reference reference = new Reference(string.Empty);
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.DigestMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
var keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(certificate));
SignedXml sxml = new SignedXml(document);
sxml.KeyInfo = keyInfo;
sxml.SigningKey = certificate.PrivateKey;
sxml.SignedInfo.SignatureMethod = Xmldsigns256;
sxml.AddReference(reference);
sxml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
sxml.ComputeSignature();
XmlElement xmlDigitalSignature = sxml.GetXml();
if (document.DocumentElement == null)
{
document.AppendChild(document.ImportNode(xmlDigitalSignature, true));
}
else
{
document.DocumentElement.AppendChild(document.ImportNode(xmlDigitalSignature, true));
}
if (document.FirstChild is XmlDeclaration)
{
document.RemoveChild(document.FirstChild);
}
MemoryStream outStream = new MemoryStream();
document.Save(outStream);
return outStream;
}