Поделиться через


Класс System.Security.Cryptography.Xml.SignedXml

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Класс SignedXml представляет собой реализацию .NET синтаксиса и обработки xml-подписи консорциума W3C (W3C), также известной как XMLDSIG (цифровая подпись XML). XMLDSIG — это стандартный, совместимый способ подписывать и проверять все или часть XML-документа или другие данные, которые можно адресовать из универсального идентификатора ресурса (URI).

Используйте класс всякий раз, когда необходимо совместно использовать подписанные SignedXml XML-данные между приложениями или организациями стандартным способом. Все данные, подписанные с помощью этого класса, можно проверить с помощью любой соответствующей реализации спецификации W3C для XMLDSIG.

Класс SignedXml позволяет создавать следующие три типа цифровых подписей XML:

Тип подписи Description
Конвертированный сигнатура Подпись содержится в подписанном XML-элементе.
Обработка подписи Подписанный XML содержится в элементе <Signature> .
Внутренняя отсоединяемая подпись Подпись и подписанный XML находятся в одном документе, но ни один элемент не содержит другого.

Существует также четвертый тип подписи, называемый внешней отсоединенной подписью, которая заключается в том, что данные и подпись находятся в отдельных XML-документах. Внешние отсоединяемые подписи не поддерживаются классом SignedXml .

Структура XML-подписи

XMLDSIG создает <Signature> элемент, содержащий цифровую подпись XML-документа или других данных, которые можно адресовать из URI. Элемент <Signature> может дополнительно содержать сведения о том, где найти ключ, который проверяет подпись и какой алгоритм шифрования использовался для подписи. Базовая структура выглядит следующим образом:

<Signature xmlns:ds="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>Base64EncodedValue==</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>AnotherBase64EncodedValue===</SignatureValue>
</Signature>

Основными частями этой структуры являются:

  • элемент <CanonicalizationMethod>;

    Задает правила перезаписи Signature элемента из XML/text в байты для проверки подписи. Значением по умолчанию в .NET является http://www.w3.org/TR/2001/REC-xml-c14n-20010315определение надежного алгоритма. Этот элемент представлен свойством SignedInfo.CanonicalizationMethod .

  • элемент <SignatureMethod>;

    Задает алгоритм, используемый для создания и проверки подписей, который был применен к <Signature> элементу для создания значения в <SignatureValue>. В предыдущем примере значение http://www.w3.org/2000/09/xmldsig#rsa-sha1 определяет подпись RSA PKCS1 SHA-1. Из-за проблем с столкновением с SHA-1 корпорация Майкрософт рекомендует модель безопасности на основе SHA-256 или более поздней версии. Этот элемент представлен свойством SignatureMethod .

  • элемент <SignatureValue>;

    Указывает криптографическую подпись для <Signature> элемента. Если эта подпись не проверяется, некоторые части <Signature> блока были изменены, и документ считается недопустимым. Если <CanonicalizationMethod> значение является надежным, это значение очень устойчиво к изменению. Этот элемент представлен свойством SignatureValue .

  • URI Атрибут <Reference> элемента

    Указывает объект данных с помощью ссылки на URI. Этот атрибут представлен свойством Reference.Uri .

    • Не указывая URI атрибут, то есть установка Reference.Uri свойства nullв значение , означает, что принимающее приложение должно знать удостоверение объекта. В большинстве случаев null URI приведет к возникновению исключения. Не используйте универсальный null код ресурса (URI), если приложение не взаимодействует с протоколом, который требует его.

    • URI Задание атрибута пустой строке указывает, что корневой элемент документа подписан, форма конвертной подписи.

    • Если значение атрибута URI начинается с #, то значение должно разрешаться в элемент в текущем документе. Эта форма может использоваться с любым из поддерживаемых типов подписей (конвертной сигнатуры, обработки подписи или внутренней отсоединяемой подписи).

    • Что-либо другое считается отсоединяемой внешней подписью ресурса и не поддерживается классом SignedXml .

  • элемент <Transforms>;

    Содержит упорядоченный список <Transform> элементов, описывающих, как подписыватель получил объект данных, который был дайджестирован. Алгоритм преобразования аналогичен методу канонизации, но вместо перезаписи <Signature> элемента он перезаписывает содержимое, определяемое атрибутом URI<Reference> элемента. Элемент <Transforms> представлен классом TransformChain .

    • Каждый алгоритм преобразования определяется как прием XML (набор узлов XPath) или байтов в качестве входных данных. Если формат текущих данных отличается от требований к входным данным преобразования, применяются правила преобразования.

    • Каждый алгоритм преобразования определяется как создание XML или байтов в качестве выходных данных.

    • Если выходные данные последнего алгоритма преобразования не определены в байтах (или не были указаны преобразования), метод канонизации используется в качестве неявного преобразования (даже если в элементе был указан <CanonicalizationMethod> другой алгоритм).

    • Значение http://www.w3.org/2000/09/xmldsig#enveloped-signature алгоритма преобразования кодирует правило, интерпретируемое как удаление <Signature> элемента из документа. В противном случае средство проверки конвертной сигнатуры будет дайджестировать документ, включая подпись, но подписыватель бы дайджестировал документ до применения подписи, что привело к разным ответам.

  • элемент <DigestMethod>;

    Определяет метод дайджеста (криптографического хэша), который будет применяться к преобразованном содержимому, определяемом атрибутом URI<Reference> элемента. Это свойство представлено свойством Reference.DigestMethod .

Выбор метода канонизации

Если не выполняется взаимодействие со спецификацией, которая требует использования другого значения, рекомендуется использовать метод канонизации .NET по умолчанию, который является алгоритмом XML-C14N 1.0, значение которого равно http://www.w3.org/TR/2001/REC-xml-c14n-20010315. Алгоритм XML-C14N 1.0 должен поддерживаться всеми реализациями XMLDSIG, особенно так как это неявное окончательное преобразование для применения.

Существуют версии канонических алгоритмов, которые поддерживают сохранение комментариев. Не рекомендуется сохранять канонические методы примечания, так как они нарушают принцип "подписать то, что видно". То есть примечания в <Signature> элементе не изменят логику обработки для того, как выполняется подпись, просто то, что такое значение сигнатуры. При сочетании с слабым алгоритмом подписи, что позволяет включать комментарии злоумышленнику, ненужную свободу принудительного столкновения хэша, что делает измененный документ законным. В платформа .NET Framework по умолчанию поддерживаются только встроенные канонизаторы. Дополнительные или пользовательские канонизаторы см. в свойстве SafeCanonicalizationMethods . Если в документе используется метод канонизации, который не находится в коллекции, представленной SafeCanonicalizationMethods свойством, CheckSignature метод вернет false.

Примечание.

Чрезвычайно оборонительное приложение может удалить любые значения, которые не ожидают, что подписи будут использоваться из SafeCanonicalizationMethods коллекции.

Являются ли ссылочные значения безопасными от изменения?

Да, <Reference> значения безопасны от изменения. .NET проверяет вычисление <SignatureValue> перед обработкой любого из <Reference> значений и связанных с ними преобразований, и будет прервать рано, чтобы избежать потенциально вредоносных инструкций по обработке.

Выберите элементы для подписывания

Рекомендуется использовать значение "" для URI атрибута (или задать Uri для свойства пустую строку), если это возможно. Это означает, что весь документ считается для вычисления дайджеста, что означает, что весь документ защищен от изменения.

Очень часто отображаются URI значения в виде привязок, таких как #foo, ссылаясь на элемент, атрибут идентификатора которого имеет значение foo. К сожалению, это легко изменить, так как это включает только содержимое целевого элемента, а не контекста. Это различие называется оболочкой подписи XML (XSW).

Если приложение считает примечания семантикой (которая не распространена при работе с XML), вместо "#xpointer(/)" и "#xpointer(id('foo'))" вместо "#foo". Версии #xpointer интерпретируются как примечания, а формы shortname исключают комментарии.

Если необходимо принять документы, которые защищены только частично, и вы хотите убедиться, что вы читаете то же содержимое, что и подпись, защищенное GetIdElement , используйте этот метод.

Рекомендации по безопасности элемента KeyInfo

Данные в необязательном <KeyInfo> элементе (т KeyInfo . е. свойстве), который содержит ключ для проверки подписи, не должны быть доверенными.

В частности, если KeyInfo значение представляет открытый открытый ключ RSA, DSA или ECDSA, документ может быть изменен, несмотря на CheckSignature то, что подпись допустима. Это может произойти, так как сущность, выполняющая изменение, просто должна создать новый ключ и повторно подписать документ с этим новым ключом. Таким образом, если приложение не проверяет, является ли открытый ключ ожидаемым значением, документ должен рассматриваться как будто он был изменен. Для этого приложение проверяет открытый ключ, внедренный в документ, и проверяет его в списке известных значений контекста документа. Например, если документ можно понять, что он выдан известным пользователем, вы проверка ключ в списке известных ключей, используемых этим пользователем.

Вы также можете проверить ключ после обработки документа с помощью CheckSignatureReturningKey метода, а не с помощью CheckSignature метода. Но для оптимальной безопасности необходимо заранее проверить ключ.

Кроме того, попробуйте использовать зарегистрированные открытые ключи пользователя, а не читать то, что находится в элементе <KeyInfo> .

Вопросы безопасности элемента X509Data

Необязательный <X509Data> элемент является дочерним <KeyInfo> элементом элемента и содержит один или несколько сертификатов X509 или идентификаторов для сертификатов X509. Данные в элементе <X509Data> также не должны быть изначально доверенными.

При проверке документа с внедренным <X509Data> элементом .NET проверяет только разрешение данных на сертификат X509, открытый ключ которого можно успешно использовать для проверки подписи документа. В отличие от вызова CheckSignature метода с verifySignatureOnly заданным параметромfalse, не выполняется проверка отзыва, доверие цепочки не проверка и срок действия не проверяется. Даже если приложение извлекает сам сертификат и передает его CheckSignature методу с verifySignatureOnly заданным параметром false, то это по-прежнему недостаточно проверки, чтобы предотвратить изменение документа. Сертификат по-прежнему должен быть проверен как подходящий для подписанного документа.

Использование внедренного сертификата подписи может предоставлять полезные стратегии смены ключей, будь то в <X509Data> разделе или в содержимом документа. При использовании этого подхода приложение должно извлечь сертификат вручную и выполнить проверку следующим образом:

  • Сертификат был выдан непосредственно или через цепочку центра сертификации (ЦС), открытый сертификат которого внедрен в приложение.

    Использование предоставленного ОС списка доверия без дополнительных проверка, таких как известное имя субъекта, недостаточно для предотвращения измененияSignedXml.

  • Сертификат проверяется, что срок действия не истек во время подписи документа (или "сейчас" для обработки документов в режиме реального времени).

  • Для долгосрочных сертификатов, выданных ЦС, поддерживающих отзыв, убедитесь, что сертификат не был отозван.

  • Субъект сертификата проверяется в соответствии с текущим документом.

Выбор алгоритма преобразования

Если вы взаимодействуете со спецификацией, которая диктует определенные значения (например, XrML), необходимо следовать спецификации. Если у вас есть конвертированная подпись (например, при подписи всего документа), необходимо использовать http://www.w3.org/2000/09/xmldsig#enveloped-signature (представленную классом XmlDsigEnvelopedSignatureTransform ). Кроме того, можно указать неявное преобразование XML-C14N, но это не обязательно. Для обстраиваемой или отсоединяемой подписи преобразования не требуются. Неявное преобразование XML-C14N заботится обо всем.

При обновлении системы безопасности, представленной бюллетенем майкрософт по безопасности MS16-035, .NET ограничивает, какие преобразования можно использовать в проверке документов по умолчанию, при этом ненадежные преобразования вызывают CheckSignature всегда возвращать false. В частности, преобразования, требующие дополнительных входных данных (указанных как дочерние элементы в XML), больше не допускаются из-за их подверженности злоупотреблений злоумышленниками. W3C рекомендует избежать преобразований XPath и XSLT, которые являются двумя основными преобразованиями, затронутыми этими ограничениями.

Проблема с внешними ссылками

Если приложение не проверяет, что внешние ссылки подходят для текущего контекста, они могут быть злоупотреблять различными уязвимостями безопасности (включая отказ в обслуживании, распределенное Рефлексия отказ в обслуживании, раскрытие информации, обход подписей и удаленное выполнение кода). Даже если приложение будет проверять внешний URI ссылки, проблема с загрузкой ресурса останется дважды: один раз, когда приложение считывает его, и один раз при SignedXml чтении. Так как нет никакой гарантии того, что приложение считывает и проверяет действия проверки документов с одинаковым содержимым, подпись не обеспечивает надежность.

Учитывая риски внешних ссылок, SignedXml при обнаружении внешней ссылки возникает исключение. Дополнительные сведения об этой проблеме см. в КБ статье 3148821.