Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: Веб-сервисы и WCF
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.82/88: Рейтинг темы: голосов - 88, средняя оценка - 4.82
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
1

Интеграция с ГИС ЖКХ и подпись SOAP без Крипто .NET и stunnel

06.04.2017, 22:27. Просмотров 17146. Ответов 168

Решил создать отдельную тему, так как в теме Интеграция с ГИС ЖКХ. Подпись SOAP и защита канала по ГОСТ (4) - C# WCF уже можно заблудиться.

Причиной написания данной куклы/тестового приложения стало желание избавиться от зависимости от Крипто .NET.

За прошедший год с момента начала использования Крипто .NET у меня к нему накопился ряд претензий, таких как:
1. Работа только с одним, своим, криптопровайдером
2. Навязчивая загрузка во все приложения, даже туда, где он не нужен
Как следствие, это приводит к невозможности использования ряда приложений, таких как, например, NUnit Framework


Не хочу сказать ничего плохого в адрес разработчиков КриптоКом.
Они и сами признают на своем форуме, что внедрение чужеродных алгоритмов шифрования в операционные системы Windows это очень непростая задача.
Но все-таки в результате Крипто .NET получился, по моему опыту, настолько глючным, что пользоваться им в работе становится весьма обременительным.

Предлагаемая кукла обеспечивает работу с ГИС ЖКХ без настоятельно навязываемых Ланитом продуктов КриптоКом, таких как stunnel и Крипто .NET.
Для работы используются стандартные вызовы CryptoAPI, так что криптопровайдера установить придется,
соответствующего полученному в УЦ ключу, CryptoPro CSP или ViPNet CSP.

Что было сделано:
1. За основу была взята реализация springjazzy (https://github.com/springjazzy/Xades) выложенная с составе примера начального уровня выложенного Anvano. Учтены/приняты во внимание замечания других участников форума
2. Была написана обертка для работы с CryptoAPI (с использованием найденного куска от Microsoft), в ней был выделен интерфейс ICryptoProvider декларирующий минимально необходимый функционал для подписи
3. Реализация springjazzy из пункта 1 была подвергнута переработке в следующих направлениях:
3.1. Был выкинут весь неиспользуемый функционал класса XadesSignedXml для облегчения чтения и понимания, что там вообще происходит
3.2. Последовательным движением в глубину текстов библиотеки Xades и замены рефлексии методов .NET на куски текста Microsoft удалось избавить класс XadesSignedXml от
криптографии .NET. Вызовы криптографии .NET были заменены на вызовы трех методов ICryptoProvider из п.2

Таким образом, сейчас подпись Xades в данном приложении осуществляется следующим образом:

C#
1
2
ICryptoProvider CryptoProvider = GetCryptoProvider(SigningSertificate);
signedXml.ComputeSignature(CryptoProvider.ComputeHash, CryptoProvider.ComputeSignature, CryptoProvider.ReverseSignature);
где:
  • signedXml - экземпляр класса XadesSignedXml из модифицированной библиотеки
  • ComputeHash - функция расчета хэша вида byte[] ComputeHash(byte[] Data)
  • ComputeSignature - функция расчета подписи вида byte[] ComputeSignature(byte[] Data)
  • ReverseSignature - свойство типа bool, показывающее библиотеке, нужно ли переворачивать полученную подпись:8 Выяснилась занятная деталь: Крипто .NET и CryptoPro CSP оба выдают верные подписи (для одного и того же сертификата), но одну из них нужно зеркально перевернуть, чтобы ее принял ГИС ЖКХ. Почему там сделано - не знаю, это наверное можно спросить в КриптоКом

  • Кукла проверена на машине где установлен как Крипто .NET так и CryptoPro CSP
  • После чего Крипто .NET был удален
  • Компьютер был перезагружен для завершения удаления (два раза, так как с первого раза Крипто .NET удаляться не захотел)
  • После этого осталась работоспособной только часть, работающая через CryptoApi

С ключами Инфотекса у меня в настоящее время возможности проверить работоспособность нет, так как тестовый ключ Инфотекса уже не рабочий.

У кого есть возможность проверить, просьба сообщить о результатах.

Из имеющихся в настоящий момент не исправленных глюков - ошибка связанная с некорректным освобождением памяти при выходе при приложения. Подозреваю, что ошибка где-то в обертке CryptoAPI, но где - пока непонятно.


В прилагаемом архиве исходные тексты куклы и релизная сборка приложения.

Отзывы и конструктивная критика принимаются.

С уважением к участникам форума,
hhmm

Дополнение от 18.10.2018:

В данной теме есть и другие решения предложенные участниками, вынесены в шапку для облегчения навигации:

1. gizmo23 предложил свой вариант библиотеки.
В основу был взят тот же проект signature-demo-net. Все ссылки в сообщении.
Первоначальное обсуждение продолжалось до post10628102

2. umatkot предложил утилиту для проверки работоспособности сервера ГИС ЖКХ. Утилита (по словам автора) использует еще более усовершенствованную версию библиотеки подписи.

3. Дополнение на тему альтернативных криптопровайдеров: месяц назад один из клиентов предоставил на опыты реальный, не тестовый ключ, ViPNet CSP выданный настоящим удостоверяющим центром. Попытка прикрутить провайдера ViPNet CSP к ГИС ЖКХ успехом не увенчалась. Несмотря на то, что на машину удалось установить два криптопровайдера одновременно и каждый из них отдельно видел и успешно читал свои ключи, попытка подключиться с ключом ViPNet CSP к ППАК ГИС ЖКХ не удалась. Проблемы возникли на транспортном уровне, такие же какие бывают у Крипто .Net клиент когда обновляется .Net Framework - 'Unable establish secure SSL/TLS channel to api.dom.dosuslugi.ru'. До подписи дело не дошло.
То ли там что-то еще нужно докупать у Инфотекса, то ли ViPNet CSP не может внедриться на транспортном уровне. В общем, у меня не получилось. Потратил один день, после чего эксперименты прекратил.

Дополнение от 24.01.2018:

4. vst377 предложил набор классов реализующих работу в ГИС ЖКХ файловых сервисов.
8
Вложения
Тип файла: zip GisBusted.zip (4.17 Мб, 197 просмотров)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.04.2017, 22:27
Ответы с готовыми решениями:

.NET 4.x Интеграция с ГИС ЖКХ. Подпись SOAP и защита канала по ГОСТ (2)
Начало темы здесь: http://www.cyberforum.ru/web-services-wcf/thread1615223.html umatkot, Да, к...

Интеграция с ГИС ЖКХ. Подпись SOAP и защита канала по ГОСТ (4)
Предыдущая тема: http://www.cyberforum.ru/web-services-wcf/thread1800721.html Здравствуйте....

Интеграция с ГИС ЖКХ. Подпись SOAP и защита канала по ГОСТ (5)
Предыдущая тема: http://www.cyberforum.ru/web-services-wcf/thread1840159.html И так мы Я и...

Интеграция с ГИС ЖКХ. Подпись SOAP и защита канала по ГОСТ (3)
Предыдущая тема: http://www.cyberforum.ru/web-services-wcf/thread1776736.html Кто нибудь знает...

Интеграция с ГИС ЖКХ. Подпись SOAP и защита канала по ГОСТ
Здравствуйте! Передо мной стоит задача интеграции с системой ГИС ЖКХ...

168
Umatkot_Primtep
96 / 80 / 18
Регистрация: 29.04.2016
Сообщений: 331
07.04.2017, 05:28 2
Громогласное УРА! Хоть от одного урода отделались! У меня было принуждением создать свой прокси сервис на машине, где стояло всего два продукта КриптоПро ЦСП и КриптоПро НЭТ, студия вместе с КриптоПро НЭТ не хотела работать- на форуме мы нашли косяк и как его исправить - вот ссылка вот ссылка. Но зачем прикручивать педали, если можно обойтись без этого.

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

Добавлено через 3 минуты
Надо будет на выходных проверить, будет ли фиддлер использовать расшифровку ГОСТа, если будет удалена КриптоПроНЭТ, так как он ругается, что неизвестный алгоритм.
0
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
07.04.2017, 21:52  [ТС] 3
Цитата Сообщение от Umatkot_Primtep Посмотреть сообщение
Есть сомнения по поводу лицензирования полученного продукта(свой подход к криптопровайдеру)
А какие сомнения, вызовы стандартных функций операционной системы.

Поправил проблему с падением по завершении, оказалось нужно счетчик ссылок в одном месте вручную подкручивать.

Нужно внести одну правку, метод в Crypto\CryptoProviders\CryptoProviderFactory.cs должен выглядеть так:


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/// <summary>
/// Получить информацию о контейнере ключа и прочее
/// </summary>
/// <param name="certificate">Сертификат</param>
/// <returns></returns>
public static MicrosoftCryptoApi.CAPI.CRYPT_KEY_PROV_INFO GetKeyContainerInformation(X509Certificate2 certificate)
    {
    bool bres;
    bool bSuccess = false;
    MicrosoftCryptoApi.SafeCertContextHandle CertContextHandle = new MicrosoftCryptoApi.SafeCertContextHandle(certificate.Handle);
    CertContextHandle.DangerousAddRef(ref bSuccess); // Вручную увеличиваем счетчик ссылок, так как еще одна ссылка сделана при помощи new выше
    if (!bSuccess)
        {
        throw new InvalidOperationException();
        }
 
    MicrosoftCryptoApi.SafeLocalAllocHandle ZeroPtr = new MicrosoftCryptoApi.SafeLocalAllocHandle(IntPtr.Zero);
    uint cbData;
    cbData = 0;
 
    bres = MicrosoftCryptoApi.CAPI.CAPISafe.CertGetCertificateContextProperty(CertContextHandle, MicrosoftCryptoApi.CAPI.CERT_KEY_PROV_INFO_PROP_ID, ZeroPtr, ref cbData);
    if (!bres)
        {
        Win32Exception ex = CryptoProviderBase.GetLastWin32Exception();
        throw ex;
        }
 
    MicrosoftCryptoApi.SafeLocalAllocHandle Ptr = null;
    MicrosoftCryptoApi.CAPI.CRYPT_KEY_PROV_INFO KeyProvInfo;
 
    try
        {
        Ptr = MicrosoftCryptoApi.CAPI.CAPISafe.LocalAlloc(0, new IntPtr(cbData));
        bres = MicrosoftCryptoApi.CAPI.CAPISafe.CertGetCertificateContextProperty(CertContextHandle, MicrosoftCryptoApi.CAPI.CERT_KEY_PROV_INFO_PROP_ID, Ptr, ref cbData);
        if (!bres)
            {
            Win32Exception ex = CryptoProviderBase.GetLastWin32Exception();
            throw ex;
            }
 
        KeyProvInfo = (MicrosoftCryptoApi.CAPI.CRYPT_KEY_PROV_INFO) Marshal.PtrToStructure(Ptr.DangerousGetHandle(), typeof(MicrosoftCryptoApi.CAPI.CRYPT_KEY_PROV_INFO));
        }
    finally
        {
        MicrosoftCryptoApi.CAPI.CAPISafe.LocalFree(Ptr.DangerousGetHandle());
        }
 
    return KeyProvInfo;
    }
0
Umatkot_Primtep
96 / 80 / 18
Регистрация: 29.04.2016
Сообщений: 331
10.04.2017, 04:55 4
Цитата Сообщение от hhmm Посмотреть сообщение
А какие сомнения, вызовы стандартных функций операционной системы
Сомнений никаких, я сам могу видеть весь код. Это у ФСБ сомнения, потому-что на лапу не даём.

Добавлено через 2 часа 52 минуты
КриптоПро в конечном итоге тоже использует Windows.Crypto.API, они поменяли только немного параметры генерации хеша на по их мнению более стойкие, чем в принятом алгоритме. Где-то читал. А для того, чтобы КриптоПро разрешили продавать их продукт - нужно лицензирование - тупо отдача бабок в ФСБ и по каким-то критериям тестирование (эти критерии мне неизвестны).
0
10.04.2017, 04:55
CCAlek
4 / 4 / 0
Регистрация: 10.04.2017
Сообщений: 19
10.04.2017, 08:26 5
Спасибо за данное решение!
Запрос выполняется на СИТ 01 без ошибок

Добавлено через 15 минут
Хотелось бы еще увидеть пример реализации импорта в ГИС ЖКХ
0
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
05.05.2017, 20:53  [ТС] 6
Цитата Сообщение от Umatkot_Primtep Посмотреть сообщение
Остаётся ещё сделать самим работу с ГОСТ
Если есть желание дописать, то в BouncyCastle уже есть реализация криптографии по ГОСТ, просто мне это не нужно так как все равно нужно ставить криптопровайдера для шифрования туннеля.

Заготовку для BouncyCastle привожу ниже:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
using System;
using System.Security.Cryptography.X509Certificates;
 
namespace Crypto.CryptoProviders
    {
    /// <summary>
    /// Класс представляющий криптопровайдера с использованием BouncyCastle
    /// </summary>
    public class BouncyCastleProvider : CryptoProviderBase
        {
        #region Конструкторы
 
        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="Certificate">Сертификат</param>
        public BouncyCastleProvider(X509Certificate2 Certificate) : base(Certificate, "BouncyCastle")
            {
            }
 
        #endregion Конструкторы
 
        #region Реализация интерфейса ICryptoProvider
 
        /// <summary>
        /// Посчитать хэш, проверено - работает правильно
        /// </summary>
        /// <param name="Data">Входной массив байт</param>
        /// <returns>хэш</returns>
        public override byte[] ComputeHash(byte[] Data)
            {
            Org.BouncyCastle.Crypto.Digests.Gost3411Digest digEng = new Org.BouncyCastle.Crypto.Digests.Gost3411Digest();
 
            digEng.BlockUpdate(Data, 0, Data.Length);
 
            byte[] digest = new byte[digEng.GetDigestSize()];
            digEng.DoFinal(digest, 0);
            return digest;
            }
 
        /// <summary>
        /// Посчитать подпись хэша
        /// </summary>
        /// <param name="Data">Входной массив байт</param>
        /// <returns>подпись в виде массива байт</returns>
        public override byte[] ComputeSignature(byte[] Data)
            {
            // TODO: это еще не написано
            throw new NotImplementedException();
            }
 
        /// <summary>
        /// Посчитать хэш и подпись к нему
        /// </summary>
        /// <param name="Data">Входной массив байт</param>
        /// <param name="Hash">Хэш</param>
        /// <param name="Signature">Подпись хэша</param>
        /// <returns>true если все хорошо</returns>
        public override bool ComputeHashAndSignature(byte[] Data, out byte[] Hash, out byte[] Signature)
            {
            Hash = ComputeHash(Data);
            Signature = ComputeSignature(Hash);
 
            if (ReverseSignature)
                {
                Signature = ReverseArray(Signature);
                }
 
            return true;
            }
 
        /// <summary>
        /// Нужно ли переворачивать подпись: .Net криптопровайдер и CryptoApi провайдеры ведут себя
        /// противоположным образом
        /// </summary>
        public override bool ReverseSignature
            {
            get
                {
                // TODO: этот вопрос нужно изучать
                /// return false;
                throw new NotImplementedException();
                }
            }
 
        #endregion Реализация интерфейса ICryptoProvider
        }
    }
1
umatkot
70 / 69 / 5
Регистрация: 15.09.2011
Сообщений: 429
Завершенные тесты: 1
24.05.2017, 08:08 7
А NetFrameworkProvider, это как я понимаю и есть этот КриптоПро.NET?

Добавлено через 44 минуты
Ясно, разобрался. Меня мучает вот что сейчас: где вставляется пароль на приватный ключ и выбирается контейнер с приватным ключом? Сам сертификат находится, а где устанавливаются именно параметры по аналогии с имеющимся вариантом:
C#
1
2
var provider = (Gost3410CryptoServiceProvider)certificate.PrivateKey;
provider.SetContainerPassword(secureString);
0
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
24.05.2017, 10:13  [ТС] 8
Цитата Сообщение от umatkot Посмотреть сообщение
где вставляется пароль на приватный ключ и выбирается контейнер с приватным ключом?
Пароль можно задать перед созданием экземпляра NetFrameworkProvider и в его конструктор передать сертификат с уже установленным паролем.
Но по мне так проще с этим не заморачиваться, а при первом запуске, когда появится окно ввода пароля CryptoPro CSP, поставить галку 'Запомнить пароль'. Можно предположить, что CryptoPro CSP сохраняет пароль в более защищенном виде чем строчка в .ini файле приложения, возможно в Защищенном хранилище (Protected Storage) операционной системы.

P.S.

Посмотрел сейчас на написанный ранее пример BouncyCastleProvider, в нем есть неточность: в методе ComputeHashAndSignature производится анализ необходимости переворачивания подписи, это неправильно, переворачивание подписи идет в библиотеке Xades в зависимости от переданного флага ReverseSignature, т.е. пример должен выглядеть так:


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        /// <summary>
        /// Посчитать хэш и подпись к нему
        /// </summary>
        /// <param name="Data">Входной массив байт</param>
        /// <param name="Hash">Хэш</param>
        /// <param name="Signature">Подпись хэша</param>
        /// <returns>true если все хорошо</returns>
        public override bool ComputeHashAndSignature(byte[] Data, out byte[] Hash, out byte[] Signature)
            {
            Hash = ComputeHash(Data);
            Signature = ComputeSignature(Hash);
            return true;
            }
0
umatkot
70 / 69 / 5
Регистрация: 15.09.2011
Сообщений: 429
Завершенные тесты: 1
24.05.2017, 11:29 9
hhmm, я пока не буду использовать BouncyCastle ввиду того, что времени очень мало, а мне надо перевести мой проект на безNETие.
По поводу ответа - спасибо, я как раз уже подобрался к CryptAcquireContext, там есть cspParameters, есть флаги, которые как раз покажут окно с вводом пароля, но у меня есть навязчивая идея подавать туда именно SecureString(Password). Я сегодня обязательно докопаюсь до этого, так как уже начал вникать во всё то, что ты сделал - это, конечно увело у меня два дня, но если бы не твои старания, я бы пару месяцев, наверное рыл...

Добавлено через 1 минуту
Цитата Сообщение от hhmm Посмотреть сообщение
сертификат с уже установленным паролем
а можно этот момент поподробнее да более наглядно? Что-то я не видел, чтобы в сам сертификат куда-то вставлялся пароль на контейнер закрытого ключа....

Я NET не использую сделал так:
C#
1
2
3
4
5
6
7
8
9
/// <summary>
        /// Получить криптопровайдер
        /// </summary>
        /// <returns></returns>
        static ICryptoProvider GetCryptoProvider(X509Certificate2 certificate)
        {
            var factory = CryptoProviderFactory.GetInstance();
            return factory.GetCryptoProvider(certificate);
        }
Мне пока больше никакие не нужны. Когда уже освоюсь в коде, буду лепить BouncyCastle и буду уже смотреть с реверсом, что да как. Сейчас полностью перенёс твои работы в свой проект, только решарпером наменял там, чтобы было меньше кода, да нагляднее, да ещё, чуть позже думаю перевести всё это дело с XML на LINQ2XML - должно ещё больше сократиться кода...

Цитата Сообщение от hhmm Посмотреть сообщение
ри первом запуске, когда появится окно ввода пароля CryptoPro CSP, поставить галку 'Запомнить пароль'
Дело в том, что функция
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        [SecurityCritical]
        public static bool CryptAcquireContext(
            [In, Out] ref SafeCryptProvHandle hCryptProv,
            [In]     [MarshalAs(UnmanagedType.LPStr)] string pwszContainer,
            [In]     [MarshalAs(UnmanagedType.LPStr)] string pwszProvider,
            [In]     uint dwProvType,
            [In]     uint dwFlags)
        {
            var parameters = new CspParameters();
            parameters.ProviderName = pwszProvider;
            parameters.KeyContainerName = pwszContainer;
            parameters.ProviderType = (int)dwProvType;
            parameters.KeyNumber = -1;
            parameters.Flags = (CspProviderFlags)((dwFlags & CryptMachineKeyset) == CryptMachineKeyset ? CspProviderFlags.UseMachineKeyStore : 0);
 
            var kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
            var entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Open);
            kp.AccessEntries.Add(entry);
            kp.Demand();
 
            var rc = CapiUnsafe.CryptAcquireContext(ref hCryptProv,
                                                     pwszContainer,
                                                     pwszProvider,
                                                     dwProvType,
                                                     dwFlags);
 
            if (!rc && Marshal.GetLastWin32Error() == NteBadKeyset)
            {
                rc = CapiUnsafe.CryptAcquireContext(ref hCryptProv,
                                                    pwszContainer,
                                                    pwszProvider,
                                                    dwProvType,
                                                    dwFlags | CryptNewkeyset);
            }
 
            return rc;
        }
в моём проекте выдаёт false ввиду того, что пароль как раз не сохранён. Я выбрал локальное хранилище в твоём проекте и функция возвращает TRUE. Пароль, видимо, хранится где-то в самом провайдере, может быть зашифрован как угодно и чем угодно, но это не суть пока...

Дело, наверное, как раз в этом
C#
1
parameters.Flags = (CspProviderFlags)((dwFlags & CryptMachineKeyset) == CryptMachineKeyset ? CspProviderFlags.UseMachineKeyStore : 0);
Добавлено через 2 минуты
0
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
24.05.2017, 11:47  [ТС] 10
Цитата Сообщение от umatkot Посмотреть сообщение
Что-то я не видел, чтобы в сам сертификат куда-то вставлялся пароль на контейнер закрытого ключа
А это тогда что:

C#
1
2
var provider = (Gost3410CryptoServiceProvider)certificate.PrivateKey;
provider.SetContainerPassword(secureString);
т.е. в моем примере в классе XadesBesSigner метод GetCryptoProvider() можно написать следующим образом:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/// <summary>
/// Получить криптопровайдера
/// </summary>
/// <returns></returns>
static ICryptoProvider GetCryptoProvider()
    {
    switch (GisBusted.GisGlobals.ProviderModel)
        {
        case GisBusted.ProviderModel.dotNetFramework:
                {
                // Устанавливаем пароль
                var provider = (Gost3410CryptoServiceProvider) GisBusted.GisGlobals.SigningCertificate.PrivateKey;
                provider.SetContainerPassword(secureString);
 
                // Далее как в оригинале
                ICryptoProvider iCryptoProvider = new NetFrameworkProvider(GisBusted.GisGlobals.SigningCertificate);
                return iCryptoProvider;
                }
        case GisBusted.ProviderModel.CryptoApi:
                {
                CryptoProviderFactory Factory = CryptoProviderFactory.GetInstance();
                ICryptoProvider iCryptoProvider = Factory.GetCryptoProvider(GisBusted.GisGlobals.SigningCertificate);
                return iCryptoProvider;
                }
        default:
                {
                throw new NotImplementedException();
                }
        }
    }
1
umatkot
70 / 69 / 5
Регистрация: 15.09.2011
Сообщений: 429
Завершенные тесты: 1
24.05.2017, 12:39 11
hhmm, спасибо, но я не могу так сделать.
C#
1
Gost3410CryptoServiceProvider
он от NET, а я его не юзаю. Мне надо сейчас вскрыть библиотеку Sharpei и разобраться. Там собака глубже зарыта. Я отпишусь, как сделаю.
Во вторых свойство Private key у меня сейчас NULL, оно заполняется в шарпее.
0
umatkot
70 / 69 / 5
Регистрация: 15.09.2011
Сообщений: 429
Завершенные тесты: 1
01.06.2017, 04:24 12
Я сделал, но даже твой исходник без изменений иногда (очень редко) выдаёт такую ошибку:
Имя сбойного приложения: vstest.executionengine.exe, версия: 14.0.23107.0, метка времени: 0x559b7b6d
Имя сбойного модуля: ntdll.dll, версия: 10.0.10240.16384, метка времени: 0x559f384f
Код исключения: 0xc0000005
Смещение ошибки: 0x0000000000087733
Идентификатор сбойного процесса: 0x1030
Время запуска сбойного приложения: 0x01d2d9ab2ef9234b
Путь сбойного приложения: C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\vstest.executionengine.exe
Путь сбойного модуля: C:\Windows\SYSTEM32\ntdll.dll

Вероятно, из-за этого:

Имя сбойного приложения: vstest.executionengine.exe, версия: 14.0.23107.0, метка времени: 0x559b7b6d
Имя сбойного модуля: ntdll.dll, версия: 10.0.10240.16384, метка времени: 0x559f384f
Код исключения: 0xc0000374
Смещение ошибки: 0x00000000000ea31c
Идентификатор сбойного процесса: 0x24f0
Время запуска сбойного приложения: 0x01d2d9a9a0495377
Путь сбойного приложения: C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\vstest.executionengine.exe
Путь сбойного модуля: C:\Windows\SYSTEM32\ntdll.dll


Добавлено через 1 минуту
Моя версия тоже. Я очень много переработал там и ещё доработаю и выложу конкретно модуль подписи без использования КриптоПро.NET
0
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
01.06.2017, 21:29  [ТС] 13
Цитата Сообщение от umatkot Посмотреть сообщение
Имя сбойного приложения: vstest.executionengine.exe, версия: 14.0.23107.0, метка времени: 0x559b7b6d
Это движок тестировщика вижуалки падает. У меня он вообще, пока КриптоПро .Net клиент стоял, валился сразу когда в него библиотека шарпея пыталась внедриться.

Но CryptoPro CSP тоже валится только в путь. Мне клиенты логи присылают, так там CryptoPro CSP частенько падает на Windows 10.

Но все же, без КриптоПро .Net клиент жизнь стала намного лучше.
0
umatkot
70 / 69 / 5
Регистрация: 15.09.2011
Сообщений: 429
Завершенные тесты: 1
02.06.2017, 15:34 14
hhmm, Да, надо это дело добить, я отладчиком смотрел, нашёл точку падения в ntdll, но особо не вникал.
У меня отрезанный есть проект - чисто с подписью XML(у него такое-же (консольный проект)), я попробую вырезать проект с криптопровайдером отдельно и потестить чисто сам CSP. Самих утечек памяти нет - я тестировал разными мониторами в цикле на подписи как очень больших договоров, так и маленьких.

Добавлено через 9 минут
По этой теме и по падению тестов.
НА самом деле вся проблема в обновлении NET framework, мне один пользователь форума КриптоПро написал, что ему удалось локализовать ошибку с установленной Шарпейкой, но для этого пришлось внутри фрэймворка в servicemodel.xml(точно сейчас не скажу, потом получу доступ - пришлю). нужно удалить целую ветку serviceModel. КриптоПро.Net перестаёт её обходить и падения устраняются совсем.

Добавлено через 10 минут
Вот так вставляется ключ в контейнер.
C#
1
2
3
4
5
6
7
8
9
10
11
/// <summary>Установка пароля доступа к контейнеру.</summary>
    /// <param name="password">Пароль доступа к контейнеру.</param>
    [SecuritySafeCritical]
    public void SetContainerPassword(SecureString password)
    {
      new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
      if (this.PublicOnly)
        throw new CryptographicException(Resources.Cryptography_CSP_NoPrivateKey);
      this.GetKeyPair();
      CPUtils.SetPin(this.safeProvHandle_, password, this.parameters_.KeyNumber);
    }
Добавлено через 7 часов 20 минут
Вот, почему падает:
Совершенно случайно удалось победить проблему.
У меня в настройках проекта установлен фреймворк 4.6.1, если зайти в web.config или app.config, затем из меню вызвать XML->Schemas
всплывет окно подключенных схем xsd для конфигов, там указаны галкой DotNetConfig.xsd и DotNetConfig45.xsd.
Нужно отключить DotNetConfig.xsd т.е. поставить крест (Do not use this schema) и перезапустить студию.
Если же после перезапуска DotNetConfig.xsd все еще подключена, проделываем нижеследующее

Закрываем студию, заходим по пути C:\Program Files (x86)\Microsoft Visual Studio 14.0\Xml\Schemas\1033 и переименовываем DotNetConfig.xsd в _DotNetConfig.xsd
Открываем студию, открываем проект, открываем файл web.config или app.config, запускаем из меню XML->Schemas.
Если все еще отображается _DotNetConfig.xsd и на нем стоит галка (use this schema), ставим крест (Do not use this schema)
Для надежности перезапускаем студию.

У меня после этих действий пропал из схем DotNetConfig.xsd и студия больше не падает.
От этих действий есть побочный эффект, автокомплит в файлах .config по-идее не будет работать в проектах с фреймворком ниже 4.5

Если будет время, проверьте у себя пожалуйста, если решит проблему, отпишусь на форуме.

Я проверил, и выяснил, что валится не только из-за подключения самих схем, а внутри, из-за обхода секций, в частности filters...

нужно было отключить секцию конфига configuration/system.serviceModel/routing/filters,
или - если копаться дальше, то можно точно узнать, что за тип был причиной падений...

Кстати странно, что ошибка именно в методе CryptoPro.Sharpei.ServiceModel.MasterServiceModel.GetDetouredTypes()
Он простой, как 5 копеек, я декомпильнул сборку, там

Цитата:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
internal static Type[] GetDetouredTypes()
{
return new Type[31]
{
typeof (CPSecurityUtils),
typeof (CPWSSecurityPolicy),
typeof (CPSecurityPolicy11),
typeof (CPCryptoHelper),
typeof (CPSymmetricSecurityProtocol),
typeof (CPWrappedKeySecurityToken),
typeof (GostAlgorithmSuite),
typeof (CPDerivedKeySecurityToken),
typeof (CPSendSecurityHeader),
typeof (CPDerivedKeyTokenEntry),
typeof (CPWrappedKeyTokenEntry),
typeof (CPWSTrustDriver),
typeof (CPSecuritySessionSecurityTokenAuthenticator),
typeof (CPSecuritySessionSecurityTokenProvider),
typeof (CPSecurityContextSecurityToken),
typeof (CPSecurityContextTokenCache),
typeof (CPInitiatorSessionSymmetricMessageSecurityProtocol),
typeof (CPAcceptorSessionSymmetricMessageSecurityProtocol),
typeof (CPDerivedKeySecurityTokenCache),
typeof (CPSecurityAlgorithmSuiteConverter),
typeof (CPServiceHostBase),
typeof (CPSspiNegotiationTokenAuthenticator),
typeof (CPSspiNegotiationTokenProvider),
typeof (CPSspiNegotiationTokenAuthenticatorState),
typeof (CPSspiNegotiationTokenProviderState),
typeof (CPDerivedKeyCachingSecurityTokenSerializer),
typeof (CPIssuedSecurityTokenProviderCoreFederatedTokenProvider),
typeof (CPChannelFactory),
typeof (CPTlsnegoTokenProvider),
typeof (cpTlsnegoTokenAuthenticator),
typeof (CPAggregateSecurityHeaderTokenResolver)
};
}

По идее ни чего криминального, единственное, если он не может какой-то тип разрезолвить.
0
umatkot
70 / 69 / 5
Регистрация: 15.09.2011
Сообщений: 429
Завершенные тесты: 1
02.06.2017, 16:06 15
Вот, переделанный немного проект. Там на сколько хватило запала всё упростил и ускорил работу в цикле.
Ещё проект содержит парочку xml для тестов.
Прошу обратить внимание, что контейнер ключа находится по отпечатку и лежит сам в локальной машине, а не в текущем пользователе.
Там ещё можно вынести рефлексию из самой подписи, чтобы не грузить либы постоянно. Короче, место для раздолья имеется. Следующий шаг будет исключение XML и работа только с криптопровайдером.
0
Вложения
Тип файла: 7z GisSignerTests.7z (656.8 Кб, 49 просмотров)
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
02.06.2017, 20:38  [ТС] 16
Цитата Сообщение от umatkot Посмотреть сообщение
Вот, переделанный немного проект. Там на сколько хватило запала всё упростил и ускорил работу в цикле.
Посмотрел ваш проект, не запускал но скомпилировал. Не запускал ибо пятница

Выскажу свое очень скромное мнение (на которое можно совсем не обращать внимание), но, как мне кажется, вы напрасно выкинули кэш открытых контейнеров. Создавать на каждую подпись экземпляр криптопровайдера и открывать контейнер для одной подписи это очень долгая операция.
0
Wer258
0 / 0 / 0
Регистрация: 17.04.2015
Сообщений: 4
06.06.2017, 10:19 17
Цитата Сообщение от hhmm Посмотреть сообщение
Предлагаемая кукла обеспечивает работу с ГИС ЖКХ без настоятельно навязываемых Ланитом продуктов КриптоКом, таких как stunnel и Крипто .NET.
Цитата Сообщение от hhmm Посмотреть сообщение
все равно нужно ставить криптопровайдера для шифрования туннеля.
Я немного не понял. Т.е. в этой реализации не нужно дополнительно включать криптоТонель, как рекомендуют ребята из ГИС ЖКХ? Или всё таки надо?
0
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
06.06.2017, 11:14  [ТС] 18
Цитата Сообщение от Wer258 Посмотреть сообщение
Я немного не понял. Т.е. в этой реализации не нужно дополнительно включать криптоТонель
Если вы имеете ввиду stunnel то он не нужен. Приложение само организует шифрованный канал подсовывая сертификат в нужное место, а дальше уже .Net Framework все организует самостоятельно.

Но чтобы .Net Framework смогла организовать шифрованный канал нужно, чтобы был установлен криптопровайдер CryptoPro CSP.
1
vst377
11 / 14 / 0
Регистрация: 02.06.2017
Сообщений: 75
07.06.2017, 06:59 19
Доброго всем дня!
Огромное спасибо hhmm за предоставленный проект!!
Хотел узнать, как были получены файлы конфигурации GisBusted_production.config, GisBusted_sit1.config, GisBusted_sit2.config? Вручную / svcutil ?
0
hhmm
55 / 55 / 0
Регистрация: 01.04.2016
Сообщений: 335
07.06.2017, 10:09  [ТС] 20
Цитата Сообщение от vst377 Посмотреть сообщение
Хотел узнать, как были получены файлы конфигурации GisBusted_production.config, GisBusted_sit1.config, GisBusted_sit2.config? Вручную
Вручную на базе того, что генерит svcutil
1
07.06.2017, 10:09
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.06.2017, 10:09

Осуществить подпись SOAP, по стандартам ГИС ГМП, принятого через TCP сокет
Здравствуйте. Требуется осуществить подпись SOAP, по стандартам ГИС ГМП, принятого через тсп сокет....

Ошибки интеграции ГИС ЖКХ
Я много тут читал форум по интеграции ГИС. На старте, впрочем, как и в последствии возникает много...

Soap, Java, Гис ЖКХ
Добрый день! Имеет ли кто опыт работы с soap в Java? Поставлена задача наладить работу с ГИС ЖКХ,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru