我使用以下脚本
创建一个键值 sn.exe -k KeyFile.snk
sn.exe -m y
sn.exe -i KeyFile.snk test
然后我使用它来验证并使用以下代码snipet签署我的xml
private void SignXml(XmlDocument xmlDoc )
{
CspParameters parms = new CspParameters(1); // PROV_RSA_FULL
parms.Flags = CspProviderFlags.UseMachineKeyStore; // Use Machine store
parms.KeyContainerName = "test"; // "CodeProject" container
parms.KeyNumber = 2; // AT_SIGNATURE
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(parms);
// Creating the XML signing object.
SignedXml sxml = new SignedXml(xmlDoc);
sxml.SigningKey = csp;
// Set the canonicalization method for the document.
sxml.SignedInfo.CanonicalizationMethod =
SignedXml.XmlDsigCanonicalizationUrl; // No comments.
// Create an empty reference (not enveloped) for the XPath
// transformation.
Reference r = new Reference("");
// Create the XPath transform and add it to the reference list.
r.AddTransform(new XmlDsigEnvelopedSignatureTransform(false));
// Add the reference to the SignedXml object.
sxml.AddReference(r);
// Compute the signature.
sxml.ComputeSignature();
// Get the signature XML and add it to the document element.
XmlElement sig = sxml.GetXml();
if (xmlDoc.DocumentElement != null)
xmlDoc.DocumentElement.AppendChild(sig);
}
public static Boolean VerifyXml(XmlDocument doc)
{
// Get the XML content from the embedded XML public key.
Stream s = null;
string xmlkey = string.Empty;
try
{
s = typeof(Program).Assembly.GetManifestResourceStream(
"LicenceVerifier.PubKey.xml");
// Read-in the XML content.
StreamReader reader = new StreamReader(s);
xmlkey = reader.ReadToEnd();
reader.Close();
}
catch (Exception e)
{
Console.Error.WriteLine("Error: could not import public key: {0}",
e.Message);
return false;
}
// Create an RSA crypto service provider from the embedded
// XML document resource (the public key).
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
csp.FromXmlString(xmlkey);
// Create the signed XML object.
SignedXml sxml = new SignedXml(doc);
try
{
// Get the XML Signature node and load it into the signed XML object.
XmlNode dsig = doc.GetElementsByTagName("Signature",
SignedXml.XmlDsigNamespaceUrl)[0];
sxml.LoadXml((XmlElement)dsig);
}
catch
{
Console.Error.WriteLine("Error: no signature found.");
return false;
}
// Verify the signature.
if (sxml.CheckSignature(csp))
return true;
else
return false;
验证总是返回false的问题,即使我使用密钥的公钥,任何想法如何解决,Signature部分看起来像:
<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/2000/09/xmldsig#rsa-sha1" />
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>XT/TOXNZ6SEe6V3c6Ulxa/rOzLE=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>t1C/ycVh/8nV1uvc9WKbOTawKQjg3luUi7717AQDHc4N+g7DDHYHAb2zvoSEUTCHIkY9UFenoZqjbLwL9/ejyef/kQe8V/jrj0GZ60BNp8ee0nXSfr91wEdhOo9qqSo/iPbnP8By9tJnbOcJG7EFWjorgMITfHGct4QXfMZFoh4=</SignatureValue>
</Signature>
我像
一样使用它们SignXml(xmlDoc); // where xmlDoc is the xmldocument i create to be signed
///////////////// TO Verify //////////////
try
{
// Create a new CspParameters object to specify
// a key container.
Console.WriteLine("Type path");
var path = Console.ReadLine();
// Create a new XML document.
XmlDocument xmlDoc = new XmlDocument();
// Load an XML file into the XmlDocument object.
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load(path);
// Verify the signature of the signed XML.
Console.WriteLine("Verifying signature...");
bool result = VerifyXml(xmlDoc);
// Display the results of the signature verification to
// the console.
if (result)
{
Console.WriteLine("The XML signature is valid.");
}
else
{
Console.WriteLine("The XML signature is not valid.");
}
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
答案 0 :(得分:3)
在我看来,你正在以错误的方式检索一个publik密钥。首先,检查文件 LicenceVerifier.PubKey.xml 是否将 Build Action 设置为 Embedded Resource 。
然后在debug:
中运行此代码typeof(Program).Assembly.GetManifestResourceNames()
确认将正确的资源名称传递给GetManifestResourceStream
。我认为您的代码应如下所示:
var asm = typeof(Program).Assembly;
s = asm.GetManifestResourceStream(asm.GetName().Name + ".LicenceVerifier.PubKey.xml");
或者,如果公钥位于子文件夹中:
var subFolder = "NAME";
var asm = typeof(Program).Assembly;
s = asm.GetManifestResourceStream(asm.GetName().Name + "." + subFolder + ".LicenceVerifier.PubKey.xml");
如果它仍然无效,则意味着您的公钥与私钥不匹配。要确认尝试以这种方式修改代码:
private static string SignXml(XmlDocument xmlDoc)
{
...
return csp.ToXmlString(false);
}
public static Boolean VerifyXml(XmlDocument doc, string xmlKey)
{
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
csp.FromXmlString(xmlKey);
...
}
var xmlKey = SignXml(xml);
var res = VerifyXml(xml, xmlKey);
如果我的怀疑得到确认,那么只需将 LicenceVerifier.PubKey.xml 的内容替换为修改后的 SignXml 版本返回的xml。
答案 1 :(得分:0)
验证者确保你有
ToolBar