CheckSignature возвращает false - PullRequest
       30

CheckSignature возвращает false

0 голосов
/ 23 сентября 2018

У меня проблема в том, что 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 Ответ

0 голосов
/ 23 сентября 2018

Если проверка подписи не удалась, полезно включить регистратор, который предоставляет дополнительную информацию о том, что пошло не так.

Вы можете включить его, добавив в файл 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, его не следует использовать.

...