长话短说,我可以很好地签署文件。但是每次验证它们都会返回错误。我浏览了 google 和 bing 的前 5 或 6 页寻找解决方案,但我发现的每一个“修复”都无济于事。任何帮助将不胜感激,因为我已经尝试解决这个问题一个多星期了。此外,这些证书的私钥不可导出,也不能。我不确定这是否重要。另外,我现在选择不包含 ValidateCertificate,因为它从来没有做到过那么远。它总是在 CheckSignature() 处失败。谢谢你。
这是我用来生成证书的内容:
makecert -a SHA256 -n "CN=JEA2.me" -pe -r -len 2048 -sy 24 -sky 签名 -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;
}