首页 > 解决方案 > c# 签署 XML 文档:x509 证书中有什么

问题描述

我正在将软件许可系统整合到我的程序中。客户端请求许可证,向我发送我需要的数据,然后我生成一个 XML 文件,这是我的程序必须在客户端检查的许可证文件。

所以我在我的开发计算机(win10)上生成了一个 x509 证书并签署了许可证文件。

X509Store store = new X509Store(StoreName, StoreLocation.CurrentUser);

store.Open(OpenFlags.ReadOnly);

X509Certificate2Collection certCollection = store.Certificates;
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, $"CN={CertificateName}", false);

X509Certificate2 cert = signingCert[0]; // has private and public
store.Close();        

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
var exportedKeyMaterial = signingCert[0].PrivateKey.ToXmlString(true);

var key = new RSACryptoServiceProvider(new CspParameters(24));
key.PersistKeyInCsp = true;
key.FromXmlString(exportedKeyMaterial);

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
// LicenseInfo is the info about her computer etc. my client provides, eg. by e-mail
using (TextReader sr = new StringReader(LicenseInfo))
{
    doc.Load(sr);
}

SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = key;
signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

Reference reference = new Reference();
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
reference.Uri = "";
reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
signedXml.AddReference(reference);

KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(cert));
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();

XmlElement sig = signedXml.GetXml();

doc.DocumentElement.AppendChild(doc.ImportNode(sig,true));
if (doc.FirstChild is XmlDeclaration)
{
    doc.RemoveChild(doc.FirstChild);
}
// and here it finally is: the license!
LicenseText = doc.OuterXml;

签名进入许可证文件,签名后将如下所示:

<License>
  <MailAddress>....</MailAddress>
  <LicenseNr>8309847560354</LicenseNr>
  <RequestTimeStamp>8/15/2019 11:28:47 AM</RequestTimeStamp>
  <ExpirationTimeStamp>8/14/2020 11:28:47 AM</ExpirationTimeStamp>
  <X5>78-BB-2F-65-4blabla45-A8-B5-4D-82</X5>
<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>Gg9WLq12JSYFh6tatRTCnGbzEzMg8PidcXK4iWwPcXg=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>JdC09BIeHcw8...q24JFVseBZWXOo==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIC8zCCAd+gAwIBAgIQgwuqv2X..........oP7f5f</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</License>

<X509Certificate/> 里面是什么?我的公钥?如果是这样,我不需要将我的公钥作为嵌入资源包含在程序中,因为它将在我的客户许可证文件中,无论如何都必须处理......对吗?不会包括我的私钥,我希望......?

这是我(尝试)验证许可证有效性的方法(不包括到期日期,仅查看许可证文件是否未被篡改)

XmlDocument xmlDocument = new XmlDocument();

xmlDocument.Load(Name); // the license file

SignedXml signedXml = new SignedXml(xmlDocument);

XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);

RSACryptoServiceProvider Key = new RSACryptoServiceProvider(new CspParameters(24));

Key.ToXmlString(false);

return signedXml.CheckSignature(Resources.PubKey.FromXmlString()); // ????? or what?

所以:

1:X509Certificate中的签名是什么?

2:验证不起作用。有什么建议么?

3:我是否将我的公钥包含在检查许可证的程序中,还是签名本身就是来源?

PS:

请不要指出这不会给我 100% 的安全性。我知道。我的问题是关于 X509,而不是关于防盗。这是另一个更广泛的问题。这很有趣,对这些东西进行编程和学习。

标签: c#x509certificateverificationsigning

解决方案


推荐阅读