Цифровая подпись XML действительна локально, но отклонена удаленным сервером при работе в контейнере Linux Docker (.NET C#

Место общения программистов C#
Ответить
Anonymous
 Цифровая подпись XML действительна локально, но отклонена удаленным сервером при работе в контейнере Linux Docker (.NET

Сообщение Anonymous »

У меня есть веб-API ASP.NET Core 5, который создает запрос SOAP, подписывает его части с помощью цифровых подписей XML (RSA-SHA256, Exclusive C14N) и отправляет его в удаленную службу SOAP.
Запрос выполняется успешно в Windows (Visual Studio 2022, IIS Express), но завершается сбоем в Linux (контейнер Docker, та же среда выполнения .NET 5), при этом удаленный сервер отвечает: «alert-signature-not-valid».
Подпись XML проверяется локально на обеих платформах — дайджест совпадает, проверка RSA проходит. Но удаленный сервер принимает только запросы, исходящие от Windows.
Среда:
  • .NET 5.0 (с поддержкой net5.0)
  • Код: Выделить всё

    System.ServiceModel.Http
    (клиент WCF, совместимый с CoreWCF)
  • Код: Выделить всё

    System.Security.Cryptography.Xml
    для SignedXml
  • Windows 10/11, RSACng работает нормально
  • Linux: Ubuntu 18.04 Docker-контейнер, RSAOpenSsl, подпись отклонена
Архитектура
Конвейер подписи + отправки:
Шаг 1. Подпишите XML-предупреждение с помощью SignedXml с помощью XmlDsigExcC14NTransform + rsa-sha256 (подпись в конверте со ссылочным URI="")
Шаг 2. WCF сериализует подписанное оповещение в конверт SOAP через XmlSerializer
Шаг 3: SigningMessageInspector.BeforeSendRequest перехватывает сообщение WCF, преобразует его в строку, добавляет wsu:Id в элемент body, подписывает тело второй ссылкой URI="#bodyId", добавляет заголовок wsse:Security с BinarySecurityToken + Signature, затем создает новое сообщение из подписанной строки XML
Шаг 4: CustomEncoder.WriteMessage перехватывает сообщение, чтобы изменить порядок элементов XML (переместить подпись в wsse:Security), затем базовый TextMessageEncoder записывает последние байты.
Что я проверил:
  • Подписи действительны локально на обеих платформах

    Код: Выделить всё

    [CAP-Sign] LOCAL SELF-VERIFICATION result=True
    
    [CAP-Sign] RE-SERIALIZED OVERALL VERIFICATION: digestOK=True, rsaOK=True, overall=True
    
    [CAP-Sign] No drift detected. Pre-sign and re-serialized body match.
    
    И Windows, и Linux создают локально действительные подписи как для тела оповещения, так и для тела SOAP.
  • Сертификат клиента mTLS отображается правильно в Linux

    Код: Выделить всё

    [mTLS-Probe] TLS handshake OK. Protocol=Tls13, LocalCertPresented=CN=MyCert..., IsMutuallyAuthenticated=True
    
    Сервер принимает соединение TLS. Проблема связана с уровнем SOAP/XML, а не с TLS.
  • Закрытый ключ сертификата работает на обеих платформах

    Код: Выделить всё

    [CertLoad] HasPrivateKey=True, RSAType=System.Security.Cryptography.RSAOpenSsl, KeySize=2048, CanSign=True
    
    Повторный импорт PFX для совместимости Linux OpenSSL завершен. Ключ может подписывать.
  • Один и тот же сертификат, одинаковый отпечаток на обеих платформах.
    Обе используют один и тот же сертификат X509 (один и тот же отпечаток, один и тот же серийный номер эмитента).
  • Код: Выделить всё

    PreserveWhitespace=false
    и Exclusive C14N используются последовательно

    Код: Выделить всё

    var xdoc = new XmlDocument { PreserveWhitespace = false };
    bodyRef.AddTransform(new XmlDsigExcC14NTransform());
    
    CRLF и LF не являются проблемой — канонизация нормализует пробелы.
  • Нет смещения XML после повторной сериализации
    Хеши тела до и после знака совпадают. XmlSerializer не изменяет XML после прикрепления подписи.
Кто-нибудь сталкивался с подобной проблемой, когда подписи SignedXml действительны локально, но отклоняются удаленным сервером только при работе в Linux (.NET 5+)? Что было исправлено?

Подробнее здесь: https://stackoverflow.com/questions/798 ... -running-i
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»