Подписанный префикс XML .NET

Есть ли способ установить префикс для подписи подписанного XML-документа (класс SignedXml в .Net)?

Так что вместо:

<Signature xmlns = "http://www.w3.org/2000/09/xmldsig#>
...
</Signature>

У меня могло быть следующее:

<ds:Signature xmlns:ds = "http://www.w3.org/2000/09/xmldsig#>
...
</ds:Signature>
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
0
8 535
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Во-первых, для этого действительно нет никаких веских причин. Эти две формы функционально эквивалентны. Любой хорошо настроенный XML-процессор будет обрабатывать их абсолютно идентично. Поэтому, если вы не пытаетесь поговорить с приложением, которое не реализует должным образом пространства имен XML, лучше (IMO) просто оставить форму по умолчанию в покое. (И даже в этом случае было бы лучше, если это вообще возможно, исправить ошибочную заявку.)

Тем не менее, вы можете вручную установить префикс для XmlElement, который возвращается SignedXml.GetXml () и его дочерними элементами, используя XPath следующим образом:

XmlElement signature = signedXml.GetXml();
foreach (XmlNode node in signature.SelectNodes(
    "descendant-or-self::*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#']"))
{
    node.Prefix = "ds";
}

Я согласен с тем, что это то же самое, и что он должен работать. Однако я не уверен, смогу ли я заставить другую сторону работать без префикса ds. Разве простое изменение префикса после сгенерированного sig не приведет к сбою проверки?

mjmcinto 20.12.2008 00:25

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

Eric Rosenberger 20.12.2008 01:44

Если вы посмотрите на класс SignedXml в Reflector, он, похоже, в значительной степени жестко привязан к тому, чтобы НЕ использовать префикс, поэтому, если вы не можете заставить его исключить элемент Signature из подписи, я не уверен, что есть какие-либо другие работоспособные варианты ...

Eric Rosenberger 20.12.2008 01:55

Для тех, кто сейчас находит эту ветку, я бы порекомендовал dotPeek от jetbrains now вместо продукта red gate. В 2008 году, безусловно, лучшим был рефлектор. Я определенно считаю, что dotPeek лучше.

Bon 17.02.2016 20:17

Это невозможно. Если вы измените XML после подписания, его невозможно будет проверить, как это было в приведенном выше примере. ИМО, это недостаток в реализации цифровой подписи MSFT, с которым вам придется смириться.

Многие люди скажут, что для этого нет причин, и что они технически правы. Но когда вы имеете дело с крупным поставщиком (т. Е. С правительством штата или банком), удачи, чтобы они поменяли его со своей стороны. Большинство эталонных реализаций включают его.

ОБНОВЛЕНИЕ: подпись подписывает все в элементе SignedInfo, поэтому, если вы обновите этот элемент постфактум, подпись больше не действительна. Вы "подделали" сообщение.

какое-либо решение по этому поводу, как мы устанавливаем префикс и проверяем его?

Oxygen 03.03.2016 10:09

Это можно сделать, но необходимо изменить класс SignedXml, чтобы добавить префикс до получения значения дайджеста узла SignedInfo.

Метод ComputeSignature будет изменен для добавления параметра префикса.

public void ComputeSignature(string prefix){...}

Когда этот метод вызывается, он вычисляет значение подписи путем переваривания значения узла SignedInfo. Если вы получите это значение без префикса «ds», а затем добавите префикс, вы получите недопустимую подпись, поэтому вам придется добавить префикс ДО получения значения дайджеста узла подписанной информации.

Это значение дайджеста создается в методе GetC14NDigest, поэтому этот метод будет изменен для добавления параметра префикса и добавления префикса ДО получения значения дайджеста.

private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
{
    XmlDocument document = new XmlDocument();
    document.PreserveWhitespace = false;
    XmlElement e = this.SignedInfo.GetXml(); //get the signedinfo nodes
    document.AppendChild(document.ImportNode(e, true));        
    Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;       
    SetPrefix(prefix, document.DocumentElement); /*Set the prefix before getting the HASH*/
    canonicalizationMethodObject.LoadInput(document);
    return canonicalizationMethodObject.GetDigestedOutput(hash);
}

Итак, теперь у вас есть значение подписи узлов SignedInfo с префиксом "ds", при этом у вас еще НЕТ xml с префиксом, поэтому, если вы просто вызовете метод GetXml, вы получите xml без префикс и, конечно же, поскольку значение подписи было вычислено с учетом префикса ds, у вас будет недействительная подпись. Чтобы избежать этого и получить структуру xml с префиксом, вам необходимо изменить метод GetXml, добавить параметр префикса и вызвать метод SetPrefix, который добавит префикс «ds» ко всем узлам в Signature Xml.

public XmlElement GetXml(string prefix)
{
    XmlElement e = this.GetXml();
    SetPrefix(prefix, e); //return the xml structure with the prefix
    return e;
}

Я оставлю здесь класс с этими модификациями

ТАМОЖЕННЫЙ КЛАСС

internal sealed class CustomSignedXml : SignedXml
{
    XmlElement obj = null;
    public CustomSignedXml (XmlDocument xml)
        : base(xml)
    {
    }

    public CustomSignedXml (XmlElement xmlElement)
        : base(xmlElement)
    {

    }

    public XmlElement GetXml(string prefix)
    {
        XmlElement e = this.GetXml();
        SetPrefix(prefix, e);
        return e;
    }

    public void ComputeSignature(string prefix)
    {
        this.BuildDigestedReferences();
        AsymmetricAlgorithm signingKey = this.SigningKey;
        if (signingKey == null)
        {
            throw new CryptographicException("Cryptography_Xml_LoadKeyFailed");
        }
        if (this.SignedInfo.SignatureMethod == null)
        {
            if (!(signingKey is DSA))
            {
                if (!(signingKey is RSA))
                {
                    throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed");
                }
                if (this.SignedInfo.SignatureMethod == null)
                {
                    this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
                }
            }
            else
            {
                this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
            }
        }
        SignatureDescription description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
        if (description == null)
        {
            throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated");
        }
        HashAlgorithm hash = description.CreateDigest();
        if (hash == null)
        {
            throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed");
        }
        this.GetC14NDigest(hash, prefix);
        this.m_signature.SignatureValue = description.CreateFormatter(signingKey).CreateSignature(hash);
    }         

    private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
    {

        XmlDocument document = new XmlDocument();
        document.PreserveWhitespace = false;
        XmlElement e = this.SignedInfo.GetXml();
        document.AppendChild(document.ImportNode(e, true));               

        Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;            
        SetPrefix(prefix, document.DocumentElement); //Set the prefix before getting the HASH
        canonicalizationMethodObject.LoadInput(document);
        return canonicalizationMethodObject.GetDigestedOutput(hash);
    }

    private void BuildDigestedReferences()
    {
        Type t = typeof(SignedXml);
        MethodInfo m = t.GetMethod("BuildDigestedReferences", BindingFlags.NonPublic | BindingFlags.Instance);
        m.Invoke(this, new object[] { });
    }

    private void SetPrefix(string prefix, XmlNode node)
    {
       foreach (XmlNode n in node.ChildNodes)
          SetPrefix(prefix, n);
       node.Prefix = prefix;
    }
}

И способ его использования

CustomSignedXml signedXml = new CustomSignedXml();
.
.//your code
. 

//compute the signature with the "ds" prefix

signedXml.ComputeSignature("ds");

//get the xml of the signature with the "ds" prefix

XmlElement xmlDigitalSignature = signedXml.GetXml("ds");

Этот код не работает, потому что он вызывает this.SignedInfo.GetXml(); в GetC14NDigest, у которого нет необходимого префикса в сгенерированных элементах XML.

AshleyS 29.07.2019 09:14

Другие вопросы по теме