c#签名XML文档:x509证书中有什么

c#签名XML文档:x509证书中有什么,c#,x509certificate,verification,signing,C#,X509certificate,Verification,Signing,我正在将软件许可证系统合并到我的一个程序中。 客户端请求许可证,向我发送所需的数据,然后我生成一个XML文件,作为我的程序必须在客户端检查的许可证文件 因此,我在开发计算机(win10)上生成一个x509证书,并对许可证文件进行签名 X509Store store = new X509Store(StoreName, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection c

我正在将软件许可证系统合并到我的一个程序中。 客户端请求许可证,向我发送所需的数据,然后我生成一个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>
因此:

1:签名中的X509证书是什么

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

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

附言:

请不要指出这不会给我100%的安全感。我知道。
我的问题是关于X509,而不是关于防盗。这是另一个更广泛的问题。编写这些内容并进行学习很有意思。

如果程序信任许可证文件的内容以了解要信任的公钥,您看不出有什么问题吗?如果其他人生成密钥并签署许可证文件,该怎么办。您的程序应该信任该输入吗?此外,请注意,这会减慢业余爱好者的速度,但不会影响任何决定删除此检查的人(他们可以将自己的密钥替换到程序中或完全编译出检查),同时会给您和您的合法客户带来不熟悉的复杂性。这不取决于许可文件的内容吗?我知道这还不够:我需要很好地隐藏检查点。我知道我永远不会得到100%的回报,这就是我的看法。客户端在接收许可证文件时需要具有公共服务器证书。这样,客户端就可以通过使用服务器证书的公钥来验证许可证文件的有效性。当然,客户端上的证书不应包含私钥。当您的licens服务器生成签名时,应该使用证书的私钥进行签名。因为许可证服务器上的证书由您控制。您在存储证书的私钥时应该没有任何问题。当我使用makecert生成证书时,我会得到一个公钥和一个私钥。同样在Win10商店中,他们一起去。这就是为什么我认为证书总是两者的结合。但事实并非如此:证书不一定包含私有证书。我引用:“不幸的是,其中一些扩展还用于其他数据,如私钥。”所以我想我的困惑并不完全令人惊讶。我猜当你运行makecert时,你很可能会得到一个*.cer文件和一个*.pvk文件。*.cer文件是包含密钥对公钥的公共证书。*.cer文件应该是您在客户端上安装的文件。您可以使用“pvk2pfx.exe”创建一个私有证书包,它将cer和pvk文件捆绑在一起。这个文件的输出是一个*.pfx文件,它很好地导入到服务器证书和私钥存储中。pfx文件应该是您在licens服务器上安装的文件。如果选择,您可以使用密码保护您的私钥。如果程序信任许可文件的内容,以了解要信任的公钥,您是否认为存在问题?如果其他人生成密钥并签署许可证文件,该怎么办。您的程序应该信任该输入吗?此外,请注意,这会减慢业余爱好者的速度,但不会影响任何决定删除此检查的人(他们可以将自己的密钥替换到程序中或完全编译出检查),同时会给您和您的合法客户带来不熟悉的复杂性。这不取决于许可文件的内容吗?我知道这还不够:我需要很好地隐藏检查点。我知道我永远不会得到100%的回报,这就是我的看法。客户端在接收许可证文件时需要具有公共服务器证书。这样,客户端就可以通过使用服务器证书的公钥来验证许可证文件的有效性。当然,客户端上的证书不应包含私钥。当您的licens服务器生成签名时,应该使用证书的私钥进行签名。因为许可证服务器上的证书由您控制。您在存储证书的私钥时应该没有任何问题。当我使用makecert生成证书时,我会得到一个公钥和一个私钥。同样在Win10商店中,他们一起去。这就是为什么我认为证书总是两者的结合。但事实并非如此:证书不一定包含私有证书。我引用:“不幸的是,其中一些扩展还用于其他数据,如私钥。”所以我想我的困惑并不完全令人惊讶。我猜当你运行makecert时,你很可能会得到一个*.cer文件和一个*.pvk文件。*.cer文件是包含密钥对公钥的公共证书。*.cer文件应该是您在客户端上安装的文件。您可以使用“pvk2pfx.exe”创建一个私有证书包,它将cer和pvk文件捆绑在一起。这个文件的输出是一个*.pfx文件,它很好地导入到服务器证书和私钥存储中。pfx文件应该是您在licens服务器上安装的文件。如果选择,则可以使用密码保护私钥。
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?