CheckSignature возвращает false
У меня проблема в том, что CheckSignature при простой подписи всегда терпит неудачу. Я использую SignXml для подписи некоторых внешних данных (в моем случае это части полезных нагрузок AS4), которые будут храниться в виде вложений MIME.
Вот код (модифицированный пример MS):
static string flXML = @"D:\Test\Example.xml";
static string flSignedXML = @"D:\Test\SignedExample.xml";
private void button1_Click(object sender, EventArgs e)
{
try
{
// Generate a signing key.
RSACryptoServiceProvider Key = new RSACryptoServiceProvider();
CreateSomeXml(flXML);
SignXmlFile(flXML, flSignedXML, Key);
bool result = VerifyXmlFile(flSignedXML, Key);
if (result)
{
Console.WriteLine("The XML signature is valid.");
}
else
{
Console.WriteLine("The XML signature is not valid.");
}
}
catch (CryptographicException ee)
{
Console.WriteLine(ee.Message);
}
}
public static void CreateSomeXml(string FileName)
{
File.WriteAllText(FileName, "<?xml version=\"1.0\" encoding=\"utf-8\"?><MyElement xmlns=\"samples\"></MyElement>");
}
private static readonly FieldInfo RefTargetTypeField = typeof(Reference).GetField("m_refTargetType", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo RefTargetField = typeof(Reference).GetField("m_refTarget", BindingFlags.Instance | BindingFlags.NonPublic);
public static void SignXmlFile(string FileName, string SignedFileName, RSA Key)
{
XmlDocument doc = new XmlDocument();
doc.Load(new XmlTextReader(FileName));
SignedXml signedXml = new SignedXml(doc);
signedXml.SigningKey = Key;
byte[] Content = System.Text.Encoding.UTF8.GetBytes("1234567890asdfghjkl");
Stream stream = new MemoryStream(Content);
var attachmentReference = new Reference(uri: "cid:xml-sample") { DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256" };
const int streamReferenceTargetType = 0;
RefTargetTypeField.SetValue(attachmentReference, streamReferenceTargetType);
RefTargetField.SetValue(attachmentReference, stream);
signedXml.AddReference(attachmentReference);
// Compute the signature.
signedXml.ComputeSignature();
XmlElement xmlDigitalSignature = signedXml.GetXml();
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
if (doc.FirstChild is XmlDeclaration)
{
doc.RemoveChild(doc.FirstChild);
}
XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
doc.WriteTo(xmltw);
xmltw.Close();
}
public static Boolean VerifyXmlFile(String Name, RSA Key)
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(Name);
SignedXml signedXml = new SignedXml(xmlDocument);
XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
{
byte[] Content = System.Text.Encoding.UTF8.GetBytes("1234567890asdfghjkl");
Stream stream = new MemoryStream(Content);
var attachmentReference = new Reference(uri: "cid:xml-sample") { DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256" };
const int streamReferenceTargetType = 0;
RefTargetTypeField.SetValue(attachmentReference, streamReferenceTargetType);
RefTargetField.SetValue(attachmentReference, stream);
signedXml.AddReference(attachmentReference);
}
// Check the signature and return the result.
signedXml.SigningKey = Key;
return signedXml.CheckSignature();
}
Кто-нибудь знает, что я делаю не так? На примечании стороны я знаю, что могу указать преобразования для дополнительных ссылок. Вопрос в том, как мне получить результат обработки ссылки в SignedXml, чтобы я тоже мог его сохранить? Например, если я указываю сжатие для преобразования по ссылке, как теперь получить результат этого сжатия?
1 ответ
Когда проверка подписи завершается неудачно, полезно включить регистратор, который предоставляет дополнительную информацию о том, что пошло не так.
Вы можете включить его, добавив его в файл app.config:
<system.diagnostics>
<sources>
<source name="System.Security.Cryptography.Xml.SignedXml" switchName="XmlDsigLogSwitch">
<listeners>
<add name="xmlDsigLogFile" />
</listeners>
</source>
</sources>
<switches>
<add name="XmlDsigLogSwitch" value="Verbose" />
<!-- possible values: Off (0) Error (1) Warning (2) Info (3) Verbose (4) -->
</switches>
<sharedListeners>
<add name="xmlDsigLogFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="XmlDsigLog.txt" />
</sharedListeners>
<trace autoflush="true">
<listeners>
<add name="xmlDsigLogFile" />
</listeners>
</trace>
</system.diagnostics>
Если ваше вложение является вложением XML, вы должны использовать XmlDsigExcC14NTransform
преобразования. Если вложение не является вложением XML, его не следует использовать.