感谢 David Brossard 的回答,我找到了解决方案。好吧,对于那些可能会徘徊的人来说,这是我的代码(签名代码必须稍作修改,因为它包含我的签名工具中的内容):
签约
private static int Sign(Options options)
{
XmlDocument document = new XmlDocument {PreserveWhitespace = false};
try
{
document.Load(options.File);
}
catch (Exception ex)
{
Console.WriteLine($"Invalid XML file: {0}.", ex.Message);
return -3;
}
XmlElement signature;
try
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);
if (!string.IsNullOrEmpty(options.Key) && File.Exists(options.Key))
{
using (StreamReader reader = new StreamReader(options.Key))
rsa.FromXmlString(reader.ReadToEnd());
}
else
{
FileInfo fi = new FileInfo(options.File);
if (fi.DirectoryName == null) return -7;
string keyFile = Path.Combine(fi.DirectoryName, "signature.key");
using (StreamWriter writer = new StreamWriter(keyFile))
writer.Write(rsa.ToXmlString(true));
}
SignedXml signedXml = new SignedXml(document) {SigningKey = rsa};
KeyInfo info = new KeyInfo();
info.AddClause(new RSAKeyValue(rsa));
signedXml.KeyInfo = info;
Reference reference = new Reference {Uri = ""};
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigC14NTransform());
signedXml.AddReference(reference);
signedXml.ComputeSignature();
signature = signedXml.GetXml();
}
catch (Exception ex)
{
Console.WriteLine($"Error signing XML file: {0}.", ex.Message);
return -4;
}
try
{
if (document.DocumentElement == null)
{
Console.WriteLine("Document has no document element.");
return -6;
}
document.DocumentElement.AppendChild(document.ImportNode(signature, true));
document.Save(options.File);
}
catch (Exception ex)
{
Console.WriteLine($"Error saving signed XML file: {0}.", ex.Message);
return -5;
}
return 0;
}
确认
public static bool Verify(XmlDocument document)
{
if (document == null) throw new ArgumentNullException(nameof(document), "XML document is null.");
SignedXml signed = new SignedXml(document);
XmlNodeList list = document.GetElementsByTagName("Signature");
if (list == null)
throw new CryptographicException($"The XML document has no signature.");
if (list.Count > 1)
throw new CryptographicException($"The XML document has more than one signature.");
signed.LoadXml((XmlElement)list[0]);
RSA rsa = null;
foreach (KeyInfoClause clause in signed.KeyInfo)
{
RSAKeyValue value = clause as RSAKeyValue;
if (value == null) continue;
RSAKeyValue key = value;
rsa = key.Key;
}
return rsa != null && signed.CheckSignature(rsa);
}