Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Кириллица в именах контейнеров (+cms) #60

Closed
emejibka opened this issue Nov 10, 2022 · 17 comments
Closed

Кириллица в именах контейнеров (+cms) #60

emejibka opened this issue Nov 10, 2022 · 17 comments
Assignees
Labels
bug Something isn't working Confirmed invalid This doesn't seem right question Further information is requested

Comments

@emejibka
Copy link

Здравствуйте.
При вычислении подписи на некоторых сертификатах получаем ошибку

   at Internal.NativeCrypto.CapiHelper.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
   at System.Security.Cryptography.Gost3410_2012_256CryptoServiceProvider.get_SafeProvHandle()
   at System.Security.Cryptography.Gost3410_2012_256CryptoServiceProvider.get_SafeKeyHandle()
   at System.Security.Cryptography.Gost3410_2012_256CryptoServiceProvider.GetKeyPair()
   at System.Security.Cryptography.Gost3410_2012_256CryptoServiceProvider..ctor(CspParameters parameters)
   at Internal.Cryptography.Pal.Windows.PkcsPalWindows.GetPrivateKey[T](X509Certificate2 certificate, Boolean silent, Boolean preferNCrypt)
   at Internal.Cryptography.Pal.Windows.PkcsPalWindows.GetPrivateKeyForSigning[T](X509Certificate2 certificate, Boolean silent)
   at System.Security.Cryptography.Pkcs.CmsSignature.Gost2012_256CmsSignature.Sign(ReadOnlySpan`1 dataHash, HashAlgorithmName hashAlgorithmName, X509Certificate2 certificate, AsymmetricAlgorithm key, Boolean silent, Oid& signatureAlgorithm, Byte[]& signatureValue)
   at System.Security.Cryptography.Pkcs.CmsSignature.Sign(ReadOnlySpan`1 dataHash, HashAlgorithmName hashAlgorithmName, X509Certificate2 certificate, AsymmetricAlgorithm key, Boolean silent, Oid& oid, ReadOnlyMemory`1& signatureValue)
   at System.Security.Cryptography.Pkcs.CmsSigner.Sign(ReadOnlyMemory`1 data, String contentTypeOid, Boolean silent, X509Certificate2Collection& chainCerts)
   at System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
...

код для вычисления подписи

                var contentInfo = new ContentInfo(rawData);
                var signedCms = new SignedCms(contentInfo, true);
                var cmsSigner = new CmsSigner(gostCert);
                cmsSigner.SignedAttributes.Add(new Pkcs9SigningTime(DateTime.Now));
                signedCms.ComputeSignature(cmsSigner, true);

На тестовых сертификатах ошибка не воспроизводится, проявляется только на некоторых сертификатах пользователя и воспроизводится регулярно.
Причём прикреплённая подпись формируется без ошибок.

Версия криптопро - 5.0.12000
Сборка corefx из коммита задачи - #53

@Fasjeit Fasjeit added the question Further information is requested label Nov 10, 2022
@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 10, 2022

Сможете приложить сертификат с ключом, на котором воспроизводится ошибка?

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 10, 2022

Так как ошибка при открытии ключа - возможные проблемы - нет доступа (прав) к закрытому ключа для пользователя, истёк срок действия закрытого ключа. Проверить это можно на клиенте через утилиту csptest (протестировать соответствующий контейнер закрытого ключа).

@emejibka
Copy link
Author

Могу, но не публично, Напишите почту.

Проверить это можно на клиенте через утилиту csptest (протестировать соответствующий контейнер закрытого ключа).

Проверяли, ошибок нет, сейчас приложу вывод.

@emejibka
Copy link
Author

/opt/cprocsp/bin/amd64/certmgr -list -thumbprint bd545df6eacf88bcb14365ac08948c6e65bdf011
Certmgr 1.1 (c) "Crypto-Pro", 2007-2021.
Program for managing certificates, CRLs and stores.
=============================================================================
1-------
Issuer              : [email protected], STREET="ул. Мишина, д. 56, стр. 2, эт. 2, пом. IX, ком. 11", C=RU, S=77 г. Москва, L=Москва, O="Акционерное Общество ""ИнфоТеКС Интернет Траст""", OGRN=1027739113049, INNLE=7743020560, CN="АО ""ИИТ"""
Subject             : E=***, C=RU, S=***, L=***, G=***, SN=***, SNILS=***, INN=***, CN=***
Serial              : 0x01D89758DB5EA9C0000A9E9A00060002
SHA1 Thumbprint     : bd545df6eacf88bcb14365ac08948c6e65bdf011
SubjKeyID           : 438dca4528108897794b1508858fbc6832cc8ea9
Signature Algorithm : ГОСТ Р 34.11-2012/34.10-2012 256 бит
PublicKey Algorithm : ГОСТ Р 34.10-2012 256 бит (512 bits)
Not valid before    : 14/07/2022  08:08:08 UTC
Not valid after     : 14/07/2023  08:08:08 UTC
PrivateKey Link     : Yes
Container           : HDIMAGE\\wqaqgvda.000\612C
Provider Name       : Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider
Provider Info       : Provider Type: 80, Key Spec: 1, Flags: 0x0
Identification Kind : Personal presence
OCSP URL            : http://cades.iitrust.ru:8777/ocsp
OCSP URL            : http://193.162.30.68:8777/ocsp
CA cert URL         : http://uc1.iitrust.ru/uc/CA-IIT-(K3)-2022.cer
CA cert URL         : http://uc2.iitrust.ru/uc/CA-IIT-(K3)-2022.cer
CA cert URL         : http://193.162.30.86/uc/CA-IIT-(K3)-2022.cer
CA cert URL         : http://193.162.30.76/uc/CA-IIT-(K3)-2022.cer
CDP                 : http://uc1.iitrust.ru/uc/CA-IIT-(K3)-2022.crl
CDP                 : http://uc2.iitrust.ru/uc/CA-IIT-(K3)-2022.crl
CDP                 : http://193.162.30.86/uc/CA-IIT-(K3)-2022.crl
CDP                 : http://193.162.30.76/uc/CA-IIT-(K3)-2022.crl
CDP                 : https://uc1.iitrust.ru/uc/CA-IIT-(K3)-2022.crl
CDP                 : https://uc2.iitrust.ru/uc/CA-IIT-(K3)-2022.crl
Extended Key Usage  : 1.3.6.1.5.5.7.3.2 Проверка подлинности клиента
                      1.3.6.1.5.5.7.3.4 Защищенная электронная почта
=============================================================================

[ErrorCode: 0x00000000]

/opt/cprocsp/bin/amd64/csptest -keyset -check -cont 'HDIMAGE\\wqaqgvda.000\612C'
CSP (Type:80) v5.0.10008 KC1 Release Ver:5.0.12000 OS:Linux CPU:AMD64 FastCode:READY:AVX.
AcquireContext: OK. HCRYPTPROV: 9163283
GetProvParam(PP_NAME): Crypto-Pro GOST R 34.10-2012 KC1 CSP
Container name: "***"
Check header passed.
Signature key is not available.
Exchange key is available. HCRYPTKEY: 0x8d6ac3
Symmetric key is not available.
UEC key is not available.
License: Cert without license
Check container passed.
Check sign passed.
Check verify signature on private key passed.
Check verify signature on public key passed.
Check import passed.
Certificate in container matches AT_KEYEXCHANGE key.
Keys in container:
  exchange key
Extensions:
  OID: 1.2.643.2.2.37.3.10
  PrivKey: Not specified - 13.01.2024 11:37:17 (UTC)
Total: SYS: 0.000 sec USR: 0.010 sec UTC: 0.080 sec
[ErrorCode: 0x00000000]

@emejibka
Copy link
Author

Отправил, пароль на архив
C3S9kbvHYTvidjAZC8gc

@emejibka
Copy link
Author

Что-нибудь ещё нужно?

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 10, 2022

Пока нет.

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 10, 2022

Проблема в кириллической кодировке (1251) имени контейнера.
При подписи получаем имя контейнера через CryptGetProvParam, получаем массив байт в 1251, но читаем его как ASCII, получаем кракозябры, пытаемся открыть контейнер с кривым именем - создаём новый контейнер вместо обращения к существующему - падаем с ошибкой.

Проблема только на Linux.

Место - GetStringProvParam

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 10, 2022

@emejibka Проблему воспроизвели и локализовали, спасибо. В ближайшее время постараемся поправить. За статусом можно следить тут.

@emejibka
Copy link
Author

Имя контейнера можно задать при установке сертификата?

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 10, 2022

В зависимости от того, как устанавливается сертификат.

  • Если сертификат устанавливается из pfx с созданием контейнера - то при установке запрашивается имя создаваемого контейнера.

  • Если сертификат устанавливается из контейнера - то имя контейнера остаётся то, какое было указано в нём. Поможет только копирование контейнера в новый с другим именем.

Как я понимаю у вас второй вариант (контейнер + сертификат в контейнере).

Если установка сертификата из контейнера - имя контейнера хранится в name.key в формате asn1. Можно записать туда имя без кириллических символов - тогда работа с контейнером будет корректной (не забыть поменять длину в asn1 теге),

Или просто удалить name.key перед установкой контейнера, тогда имя контейнера будут соответствовать имени папки.

Т.е. срочный "грязный фикс" для клиента будет таким - сохранить файлы контейнера, удалить контейнер через csptest, удалить файл name.key, установить контейнер с сертификат из него.

@Fasjeit Fasjeit changed the title Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Cryptography error Кириллица в именах контейнеров (+cms) Nov 10, 2022
@Fasjeit Fasjeit added bug Something isn't working invalid This doesn't seem right Confirmed labels Nov 10, 2022
@Fasjeit Fasjeit self-assigned this Nov 10, 2022
@emejibka
Copy link
Author

Как я понимаю у вас второй вариант (контейнер + сертификат в контейнере).
Не, на клиенте делаем экспорт сертификата в pfx, на сервере импортируем его с помощью команды
certmgr -install -pfx -file "путь к файлу" -silent -pin "пароль"

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 11, 2022

Через certmgr, судя по всему, не задаётся имя контейнера, а берётся из серта...
Тогда остаётся такой вариант.

  • Установить pfx (установится в некоторый контейнер_1)
  • Скопировать контейнер в контейнер с именем контейнер_2 (без кириллицы)
  • Удалить сертификат и исходный контейнер_1
  • Установить сертификат без привязки к закрытому ключу (без создания контейнера)
  • Привязать установленный сертификат к контейнер_2

@emejibka
Copy link
Author

Уже можно попробовать тестовую сборку или ещё рано?

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 15, 2022

Да, можно пробовать сборку
https://ci.appveyor.com/project/CryptoPro/corefx/builds/45372589

N.B. В текущей версии используется рантайм 3.1.30. Возможно придётся установить соотвествующий рантайм и SDK.

@emejibka
Copy link
Author

Спасибо, с обновлением ошибка не воспроизводится

@Fasjeit
Copy link
Collaborator

Fasjeit commented Nov 17, 2022

Windows работает и так, понимает, что там 1251.

Для Linux проблема была в том, что csp возвращала 1251, но дотнет работал с ASCII. В результате получали кракозябры + испорченные байте (т.к. ascii заменял непечатные символы). UTF8, UTF16, UTF7 - давали аналогичный результата.
Решение - по умолчанию используем на Linux кодировку Latin1, которая умеет декодировать любой массив байт. В результате хотя бы имеем возможность открыть контейнер, имя которого получено из сертификата с использованием GetProvParam (да, в cspParams будут кракозябры, но CryptAcqureContext на вход получит нужный массив байт, так как Latin1 не портит байты).

Если же на Linux уже зарегистрирована кодировка 1251 - используем её (делается отдельно через пакет System.Text.Encoding.CodePages с последующим вызовом Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)), после чего в cspParams будет попадать корректная строка. (Это же надо использовать, если кто то захочет руками открыть кириллический контейнер)

Статической проперти Encoding.Latin1 в "сборочном" рантайме по каким то причинам нет, но можно пользоваться Latin1 через Encoding.GetEncoding(28591), что и делаем.

Тестов не будет, подробнее в связанном запросе для libcore https://gitlab.cp.ru/cloud/misc/libcore/-/issues/12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Confirmed invalid This doesn't seem right question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants