Запрос выполняется успешно в Windows (Visual Studio 2022, IIS Express), но завершается сбоем в Linux (контейнер Docker, та же среда выполнения .NET 5), при этом удаленный сервер отвечает: «alert-signature-not-valid».
Подпись XML проверяется локально на обеих платформах — дайджест совпадает, проверка RSA проходит. Но удаленный сервер принимает только запросы, исходящие от Windows.
Среда:
- .NET 5.0 (с поддержкой net5.0)
- (клиент WCF, совместимый с CoreWCF)
Код: Выделить всё
System.ServiceModel.Http - для SignedXml
Код: Выделить всё
System.Security.Cryptography.Xml - 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 записывает последние байты.
Что я проверил:
- Подписи действительны локально на обеих платформах
И Windows, и Linux создают локально действительные подписи как для тела оповещения, так и для тела SOAP.
Код: Выделить всё
[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. - Сертификат клиента mTLS отображается правильно в Linux
Сервер принимает соединение TLS. Проблема связана с уровнем SOAP/XML, а не с TLS.
Код: Выделить всё
[mTLS-Probe] TLS handshake OK. Protocol=Tls13, LocalCertPresented=CN=MyCert..., IsMutuallyAuthenticated=True - Закрытый ключ сертификата работает на обеих платформах
Повторный импорт PFX для совместимости Linux OpenSSL завершен. Ключ может подписывать.
Код: Выделить всё
[CertLoad] HasPrivateKey=True, RSAType=System.Security.Cryptography.RSAOpenSsl, KeySize=2048, CanSign=True - Один и тот же сертификат, одинаковый отпечаток на обеих платформах.
Обе используют один и тот же сертификат X509 (один и тот же отпечаток, один и тот же серийный номер эмитента). - и Exclusive C14N используются последовательно
Код: Выделить всё
PreserveWhitespace=falseCRLF и LF не являются проблемой — канонизация нормализует пробелы.Код: Выделить всё
var xdoc = new XmlDocument { PreserveWhitespace = false }; bodyRef.AddTransform(new XmlDsigExcC14NTransform()); - Нет смещения XML после повторной сериализации
Хеши тела до и после знака совпадают. XmlSerializer не изменяет XML после прикрепления подписи.
Подробнее здесь: https://stackoverflow.com/questions/798 ... -running-i
Мобильная версия