Получающая сторона не может проверить подписанное сообщение XML - PullRequest
4 голосов
/ 17 марта 2020

Я пытаюсь подписать XML с C# в соответствии со спецификацией c, выданной нам для нашего тестового приложения. Мы должны:

  1. Канонизировать сообщение.
  2. Используйте алгоритм дайджеста для создания дайджеста всего сообщения.
  3. Добавьте дайджест к элементу Signed Info.
  4. Канонизация подписанной информации.
  5. Ввод закрытого ключа и канонизированной подписанной информации в указанный алгоритм подписи для создания цифровой подписи.
  6. Добавление сгенерированной цифровой подписи к элементу подписи.

Это то, что у меня сейчас есть.

public static XmlElement Sign(XmlDocument msgDoc)
{
    XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform();
    transform.LoadInput(msgDoc);
    msgDoc.Load(transform.GetOutput() as Stream);

    var signedXml = new SignedXml(msgDoc)
    {
        SigningKey = Certificate.GetRSAPrivateKey(),
    };

    signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

    var reference = new Reference();
    reference.AddTransform(new XmlDsigEnvelopedSignatureTransform(true));
    reference.AddTransform(new XmlDsigC14N11Transform()); // Custom transform
    reference.Uri = string.Empty;
    reference.DigestMethod = SignedXml.XmlDsigSHA256Url;

    signedXml.SignedInfo.AddReference(reference);

    KeyInfo keyInfo = new KeyInfo();
    var keyInfoData = new KeyInfoX509Data();
    keyInfoData.AddIssuerSerial(CertManager.Certificate.Issuer, CertManager.Certificate.SerialNumber);
    keyInfoData.AddSubjectName(CertManager.Certificate.Subject);
    keyInfo.AddClause(keyInfoData);
    signedXml.KeyInfo = keyInfo;

    signedXml.ComputeSignature();
    XmlElement signature = signedXml.GetXml();

    // This part until the return was done to ensure we get the 'ds' prefix.
    // Code taken from: https://stackoverflow.com/questions/30579938/generate-digital-signature-but-with-a-specific-namespace-prefix-ds
    SetPrefix("ds", signature);
    signedXml.LoadXml(signature);
    signedXml.SignedInfo.References.Clear();
    signedXml.ComputeSignature();        
    ReplaceSignature(signature, Convert.ToBase64String(signedXml.SignatureValue));
    XmlNode signatureElement = msgDoc.ImportNode(signature, true);

    return msgDoc.DocumentElement.InsertAfter(msgDoc.ImportNode(signature, true), msgDoc.DocumentElement.FirstChild) as XmlElement;
}

Алгоритм дайджеста: http://www.w3.org/2001/04/xmlenc#sha256

Алгоритм канонизации: http://www.w3.org/2001/10/xml-exc-c14n#

Мы используем два преобразования: http://www.w3.org/2000/09/xmldsig#enveloped -подпись и http://www.w3.org/2006/12/xml-c14n11

Имею на другой стороне включена трассировка, которая должна проверять сообщение, и это, кажется, единственное место, где происходит сбой в журнале трассировки:

[SignedXml # 0071d445, VerificationFailure] Проверка не пройдена, проверка SignedInfo .

I ' Мы убедились, что Certificate, используемый в процессе подписи, является моим личным сертификатом, а другая сторона использует сертификат publi c для процесса проверки.

Что еще мне не хватает?

Редактировать:

Мы можем проверять сообщения, которые мы получаем с их стороны. Я не могу предоставить какой-либо код проверки того, как они проверяют сообщения, потому что он не передан нам.

Это пример того, что мы отправляем:

<Message xmlns="urn:tch">
  <AppHdr>
    <head:Fr xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
      <head:ID>
        <head:MemberId>1234245</head:MemberId>
      </head:ID>
    </head:Fr>
    <head:To xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
      <head:ID>
        <head:MemberId>123345345</head:MemberId>
      </head:ID>
    <head:Date xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">2020-03-16T22:03:24</head:Date>
    <head:Sgntr xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
          <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
          <ds:Reference URI="">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
              <ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>fV61VLaSYGyW+G+LxZaLfGdOlAVmpJvusoJ792IKblw=</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>xlg1Q4hdQoCo+x4rJKWn1UwLwdshonx0dg5Z0bIAsFuBWOJGyVescQBFEZEbUHcgLq2TQZT6PBhH3F2RR4aYTnc9IY0mHRq5rJEpVfXnQZdwCw7SIhkMMIOi5rAgQ5gdLmQlbLWFm8V4+1DTE7QWiCALEkarJQcdU4n9E2rGrSM48H1NFHHC+m8J5eHcGFyRcBwSF712ihGDNvweGhwneR4JeGxyQ3Dc1pSkzkr0oOJDY0vgwIuMZIMvl6Fh98D3QByDadZqFah88uv+TWZy01B9rdfhgCP7gdeiP9fof90jnitQ4c/3XksjieLbWQxWmQ1TPoRQswDuXf731T6kmw==</ds:SignatureValue>
        <ds:KeyInfo>
          <ds:X509Data>
            <ds:X509IssuerSerial>
              <ds:X509IssuerName>CN=ABC, DC=AAA, DC=BBB, DC=CCC</ds:X509IssuerName>
              <ds:X509SerialNumber>75822323454364025267732697561489775234425345</ds:X509SerialNumber>
            </ds:X509IssuerSerial>
            <ds:X509SubjectName>E=something@somewhere.com, CN=ABC.com, OU=Internet Services, O=AAA, L=Someplace, S=somewhere, C=US</ds:X509SubjectName>
          </ds:X509Data>
        </ds:KeyInfo>
      </ds:Signature>
    </head:Sgntr>
  </AppHdr>
  <TestMessage>
    <mr:zzzz.002.001.01 xmlns:mr="urn:iso:std:iso:20022:tech:xsd:zzzz.002.001.01">
      <mr:Ref>
        <mr:Ref>20200316220315134567890122203156779</mr:Ref>
      </mr:Ref>
  </TestMessage>
</Message>

Редактировать: Если кто-то и создаст Например, используя вышеуказанную информацию для подписи, я приму ответ.

...