Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline yury.kerbitskov  
#1 Оставлено : 3 ноября 2017 г. 16:54:12(UTC)
yury.kerbitskov

Статус: Новичок

Группы: Участники
Зарегистрирован: 03.11.2017(UTC)
Сообщений: 4

Сказал(а) «Спасибо»: 5 раз
Добрый день, коллеги!

Вводная.
Моя задача до банального просто: есть массив байт, который надо подписать закрытым ключом по алгоритму ГОСТ 3410 2012 256, а хэш по ГОСТ 3411 2012 256.
Если я использую
Код:
Gost3410_2012_256CryptoServiceProvider

, то у меня отлично получается подписать и проверить в дальнейшем подпись. И я уверен какие алгоритмы используются для хэширования и подписи, так как использую конкретные классы.
Теперь мне необходимо сохранить всё это в формате CMS.
Для этого я использую примеры из SDK, которые прекрасно работают. Но у меня есть отличие от примеров, которое, заключается, во-первых, в том, что сертификат свой я беру из контейнера крипто про, а во-вторых я сам делаю проверку, выдан ли он доверенным центром. Получаю сертификат следующим образом (2 варианта):
Код:

byte[] data =
	{
		59, 4, 248, 102, 77, 97, 142, 201, 21, 12, 224, 93, 25, 41, 100, 197, 213, 134, 130, 135
	};

CspParameters cp = new CspParameters
   {						   
	   KeyContainerName = "ContainerName",
	   ProviderType = 80,
	   ProviderName = "Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider",
	   KeyPassword = "password".ToSecure(),
	   Flags = CspProviderFlags.NoPrompt,
   };

Gost3410_2012_256CryptoServiceProvider gost = new Gost3410_2012_256CryptoServiceProvider(cp);

ContentInfo contentInfo = new ContentInfo(data);
SignedCms signedCms = new SignedCms(contentInfo);
//Вариант 1. Пытался брать сертификат из объекта
CmsSigner cmsSigner = new CmsSigner(gost.ContainerCertificate);
//Вариант 2. Пытался брать сертификат из объекта CspParameters
//CmsSigner cmsSigner = new CmsSigner(cp);
signedCms.ComputeSignature(cmsSigner);
WriteLine(Convert.ToBase64String(signedCms.Encode()));


Если использовать Вариант 1, то получаю сообщение: "Не удается построить цепочку сертификатов для доверенного корневого центра.". Полагаю, что криптопровайдер пытается проверить доверенность сертификата, но мне этого не надо, так как я это делаю сам. Отсюда первый вопрос: как можно это отключить?

Если использовать Вариант 2, то получаю сообщение: "Ключ не существует". Второй вопрос: Почему он не может найти ключ? При этом с ключами проблем нет. Они находятся, если производить подпись через класс
Код:
Gost3410_2012_256CryptoServiceProvider


Ещё один вопрос: если я использую SignedCms и CmsSigner, то каким образом выбирается алгоритм подписи и хэша? Берётся из сертификата? Но в сертификате указано несколько алгоритмов. Какой из них выбирается?

Заранее благодарю за любую помощь.
Offline Максим Коллегин  
#2 Оставлено : 3 ноября 2017 г. 20:28:46(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
Алгоритм подписи однозначно определяется алгоритмом ключа, а вот алгоритм хэширования CSP попытается угадать. Лучше задавать его явно.
У меня отработал первый вариант без ошибок, root в доверенные не добавлял.
Создавая ключ из параметров, сертификат в подпись не попадёт. Но почему он его не находит - пока не знаю.
Знания в базе знаний, поддержка в техподдержке
thanks 1 пользователь поблагодарил Максим Коллегин за этот пост.
yury.kerbitskov оставлено 08.11.2017(UTC)
Offline Максим Коллегин  
#3 Оставлено : 3 ноября 2017 г. 20:32:15(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
А во втором случае MSFT делает сертификат сам, естественно 1 типа. Мы этот сценарий не отпрабатывали и поддерживать его не вижу большого смысла:
Код:
        // for Key ID signing only
        [SecuritySafeCritical]
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        internal static unsafe X509Certificate2 CreateDummyCertificate (CspParameters parameters) {
            SafeCertContextHandle handle = SafeCertContextHandle.InvalidHandle;

            // hProv
            SafeCryptProvHandle hProv = SafeCryptProvHandle.InvalidHandle;
            UInt32 dwFlags = 0;
            if (0 != (parameters.Flags & CspProviderFlags.UseMachineKeyStore))
            {
                dwFlags |= CAPI.CRYPT_MACHINE_KEYSET;
            }
            if (0 != (parameters.Flags & CspProviderFlags.UseDefaultKeyContainer))
            {
                dwFlags |= CAPI.CRYPT_VERIFYCONTEXT;
            }
            if (0 != (parameters.Flags & CspProviderFlags.NoPrompt))
            {
                dwFlags |= CAPI.CRYPT_SILENT;
            }
            bool rc = CAPI.CryptAcquireContext(ref hProv,
                                               parameters.KeyContainerName,
                                               parameters.ProviderName,
                                               (uint)parameters.ProviderType,
                                               dwFlags);
            if (!rc)
                throw new CryptographicException(Marshal.GetLastWin32Error());

            // pKeyProvInfo
            CAPI.CRYPT_KEY_PROV_INFO KeyProvInfo = new CAPI.CRYPT_KEY_PROV_INFO();
            KeyProvInfo.pwszProvName       = parameters.ProviderName;
            KeyProvInfo.pwszContainerName  = parameters.KeyContainerName;
            KeyProvInfo.dwProvType         = (uint)parameters.ProviderType;
            KeyProvInfo.dwKeySpec          = (uint)parameters.KeyNumber ;
            KeyProvInfo.dwFlags            = (uint)((parameters.Flags & CspProviderFlags.UseMachineKeyStore) == CspProviderFlags.UseMachineKeyStore ? CAPI.CRYPT_MACHINE_KEYSET : 0);

            SafeLocalAllocHandle pKeyProvInfo = CAPI.LocalAlloc(CAPI.LPTR, 
                                                                new IntPtr(Marshal.SizeOf(typeof(CAPI.CRYPT_KEY_PROV_INFO))));
            Marshal.StructureToPtr(KeyProvInfo, pKeyProvInfo.DangerousGetHandle(), false);

            // Signature
            CAPI.CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = new CAPI.CRYPT_ALGORITHM_IDENTIFIER();
            SignatureAlgorithm.pszObjId = CAPI.szOID_OIWSEC_sha1RSASign;

            SafeLocalAllocHandle pSignatureAlgorithm = CAPI.LocalAlloc(CAPI.LPTR, 
                                                                new IntPtr( Marshal.SizeOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER))));
            Marshal.StructureToPtr(SignatureAlgorithm, pSignatureAlgorithm.DangerousGetHandle(), false);

            // pSubjectIssuerBlob
            X500DistinguishedName subjectName = new X500DistinguishedName("cn=CMS Signer Dummy Certificate");
            fixed (byte * pbOctets = subjectName.RawData) {
                CAPI.CRYPTOAPI_BLOB SubjectIssuerBlob = new CAPI.CRYPTOAPI_BLOB();
                SubjectIssuerBlob.cbData = (uint)subjectName.RawData.Length;
                SubjectIssuerBlob.pbData = new IntPtr(pbOctets);

                handle = CAPI.CAPIUnsafe.CertCreateSelfSignCertificate(hProv,
                                                                       new IntPtr(&SubjectIssuerBlob),
                                                                       1,
                                                                       pKeyProvInfo.DangerousGetHandle(),
                                                                       pSignatureAlgorithm.DangerousGetHandle(),
                                                                       IntPtr.Zero,  //StartTime
                                                                       IntPtr.Zero,  //EndTime
                                                                       IntPtr.Zero); //Extensions
            }

            Marshal.DestroyStructure(pKeyProvInfo.DangerousGetHandle(), typeof(CAPI.CRYPT_KEY_PROV_INFO));
            pKeyProvInfo.Dispose();
            Marshal.DestroyStructure(pSignatureAlgorithm.DangerousGetHandle(), typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER));
            pSignatureAlgorithm.Dispose();

            if (handle == null || handle.IsInvalid)
                throw new CryptographicException(Marshal.GetLastWin32Error());

            X509Certificate2 certificate = new X509Certificate2(handle.DangerousGetHandle());
            handle.Dispose();
            return certificate;
        }
    }
Знания в базе знаний, поддержка в техподдержке
thanks 1 пользователь поблагодарил Максим Коллегин за этот пост.
yury.kerbitskov оставлено 08.11.2017(UTC)
Offline yury.kerbitskov  
#4 Оставлено : 8 ноября 2017 г. 14:37:08(UTC)
yury.kerbitskov

Статус: Новичок

Группы: Участники
Зарегистрирован: 03.11.2017(UTC)
Сообщений: 4

Сказал(а) «Спасибо»: 5 раз
Спасибо за помощь!

По поводу алгоритма и ключа из параметров понял, буду использовать первый вариант. Первый вариант у меня отработал только после добавления строки:
Код:
cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;


Правильно ли я задаю явно хэш алгоритм? Задаю следующим образом (ГОСТ 3411 2012 256):
Код:
cmsSigner.DigestAlgorithm = Oid.FromOidValue("1.2.643.7.1.1.2.2", OidGroup.HashAlgorithm);

Отредактировано пользователем 8 ноября 2017 г. 16:21:54(UTC)  | Причина: ошибся в oid

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.