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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Roberto1  
#1 Оставлено : 11 марта 2012 г. 22:02:23(UTC)
Roberto1

Статус: Участник

Группы: Участники
Зарегистрирован: 12.01.2012(UTC)
Сообщений: 19
Откуда: Kazan RF

Добрый день!

Подскажите пожалуйста.

Инфа из документации:

Цитата:
ЭЦП формируется согласно требованиям ГОСТ Р 34.10-2001 ("Информационная технология. Криптографическая защита информации. Процессы формирования и проверки электронной цифровой подписи") и ГОСТ Р 34.11-94 ("Информационная технология. Криптографическая защита информации. Функция хэширования"). Программный продукт КриптоПро CSP 2.0 компании КриптоПро удовлетворяет указанным условиям. ЭЦП представляет собой строку, закодированную в BASE64 (RFC3548).


в старом варианте было реализовано так:
Код:
            string retVal = "";
            IntPtr hCryptoProvider = IntPtr.Zero;
            IntPtr hPubKey = IntPtr.Zero;
            IntPtr hHash = IntPtr.Zero;
                ...               

                if (!Crypt32Wrapper.CryptAcquireContext(out hCryptoProvider, containerName, null, TYPE, 0))
                ...               
                int code = Crypt32Wrapper.CryptGetUserKey(hCryptoProvider, Crypt32Wrapper.AT_SIGNATURE, ref hPubKey);
                ...
                if (!Crypt32Wrapper.CryptCreateHash(hCryptoProvider, CERT_ALG_ID, IntPtr.Zero, 0, out hHash))
                ...
                byte[] buffer = encoding.GetBytes(toSign);
                if (!Crypt32Wrapper.CryptHashData(hHash, buffer, buffer.Length, 0))
                ...
                uint signatureLength = 0;
                if (!Crypt32Wrapper.CryptSignHash(hHash, Crypt32Wrapper.AT_KEYEXCHANGE, null, 0, null, ref signatureLength))
                ...
                byte[] signature = new byte[signatureLength];
                if (!Crypt32Wrapper.CryptSignHash(hHash, Crypt32Wrapper.AT_KEYEXCHANGE, null, 0, signature, ref signatureLength))
                retVal = Convert.ToBase64String(signature, 0, (int)signatureLength);


Делаю так
1.
Код:
Gost3410CryptoServiceProvider prov = (Gost3410CryptoServiceProvider)certificate.PrivateKey;
SecureString s = new SecureString();
// заполняем пароль... например так
s.AppendChar('1');
// и передаем его в провайдер.
prov.SetContainerPassword(s);


2.
Цитата:
// Открываем файл и вычисляем хеш-функцию, ( в дальнейшем просто стрим планирую использовать)
using (FileStream inStream = new FileStream(sourceFile,
FileMode.Open, FileAccess.Read))
{
myhash.ComputeHash(inStream);
}

// Получаем подсчитанное значение хеш-функции.
byte[] hashValue = myhash.Hash;


3.
//подписываю
prov.SignHash(myhash.Hash);

Все этого достаточно? или есть еще какие подводные камни?

Отредактировано пользователем 12 марта 2012 г. 14:16:29(UTC)  | Причина: Не указана

Offline Roberto1  
#2 Оставлено : 12 марта 2012 г. 18:41:06(UTC)
Roberto1

Статус: Участник

Группы: Участники
Зарегистрирован: 12.01.2012(UTC)
Сообщений: 19
Откуда: Kazan RF

Формирование эцп похоже заработало, а вот с проверкой трудности.

ЭЦП проверяется публичным ключом отправителя. У меня есть сертификат с сервера с публичным ключом.
У Gost3410CryptoServiceProvider вижу функцию VerifySignature, в принципе понимаю как ее использовать.

Подскажите, пожалуйста, как создать Gost3410CryptoServiceProvider без приватного ключа!? или куда капать.

Раньше делалось так. Сейчас хочу сертификат брать из хранилища, а не из файла как в примере.

Код:
 FileInfo fi = new FileInfo(serverCertFilePath);
                uint certLen;
                byte[] cert = new byte[fi.Length];
                using (FileStream fs = File.OpenRead(serverCertFilePath))
                {
                    certLen = (uint)fs.Read(cert, 0, (int)fi.Length);
                    fs.Close();
                }

                //hCertContext = Crypt32Wrapper.CertCreateCertificateContext(CryptoPro.CERT_ENCODING, cert, (uint)cert.Length);
                hCertContext =                   Crypt32Wrapper.CertCreateCertificateContext( CryptoPro.PKCS_7_ASN_ENCODING | CryptoPro.X509_ASN_ENCODING, cert, (uint)cert.Length);
                if (hCertContext == IntPtr.Zero)
                {
                  ...
                }
                Crypt32Wrapper.CryptAcquireContext(out hCryptoProvider, null, null, CryptoPro.TYPE, Crypt32Wrapper.CRYPT_VERIFYCONTEXT);
                IntPtr pCertInfo = (IntPtr)Marshal.ReadInt32(hCertContext, 12);
                IntPtr pSubjectPublicKeyInfo = (IntPtr)(pCertInfo.ToInt32() + 56);
                Crypt32Wrapper.CryptImportPublicKeyInfo(hCryptoProvider, CryptoPro.CERT_ENCODING, pSubjectPublicKeyInfo, out hPubKey);
                Crypt32Wrapper.CryptCreateHash(hCryptoProvider, (uint)CryptoPro.CERT_ALG_ID, IntPtr.Zero, 0, out hHash);


                byte[] buffer = encoding.GetBytes(body);
                Crypt32Wrapper.CryptHashData(hHash, buffer, buffer.Length, 0);

                byte[] verifySignature = Convert.FromBase64String(signature);
                retVal = Crypt32Wrapper.CryptVerifySignature(hHash, verifySignature, verifySignature.Length, hPubKey, null, 0);

Отредактировано пользователем 12 марта 2012 г. 18:45:02(UTC)  | Причина: Не указана

Online Андрей Писарев  
#3 Оставлено : 12 марта 2012 г. 18:59:37(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,517
Мужчина
Российская Федерация

Сказал «Спасибо»: 555 раз
Поблагодарили: 2252 раз в 1757 постах
а в SDK разве нет примеров проверки ЭЦП?

Техническую поддержку оказываем тут
Наша база знаний
Offline Roberto1  
#4 Оставлено : 12 марта 2012 г. 19:26:36(UTC)
Roberto1

Статус: Участник

Группы: Участники
Зарегистрирован: 12.01.2012(UTC)
Сообщений: 19
Откуда: Kazan RF

Примеров куча, вижу смотрю, но целой картины не вижу.

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

Тут сложность именно в использовании публичного ключа из сертификата. Как в примере что я привел выше.

Подпись тоже формируется не верно говорят.

Помогите пожалуйста.

Отредактировано пользователем 12 марта 2012 г. 19:41:37(UTC)  | Причина: Не указана

Offline Roberto1  
#5 Оставлено : 13 марта 2012 г. 14:05:51(UTC)
Roberto1

Статус: Участник

Группы: Участники
Зарегистрирован: 12.01.2012(UTC)
Сообщений: 19
Откуда: Kazan RF

формирование ЭЦП заработало нормально после корректировки кодировки.

Код:
            using (MemoryStream stream = new MemoryStream(encoding.GetBytes(body)))
            {
                myhash.ComputeHash(stream);
            }


С проверкой вопрос остался открытым. Хелп.
Online Андрей Писарев  
#6 Оставлено : 13 марта 2012 г. 14:22:05(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,517
Мужчина
Российская Федерация

Сказал «Спасибо»: 555 раз
Поблагодарили: 2252 раз в 1757 постах
Roberto1 написал:
формирование ЭЦП заработало нормально после корректировки кодировки.

Код:
            using (MemoryStream stream = new MemoryStream(encoding.GetBytes(body)))
            {
                myhash.ComputeHash(stream);
            }


С проверкой вопрос остался открытым. Хелп.


как можно Хелп, если нет ни примеров ... файл+эцп, ни кода ... ?
Или код из SDK не работает?
Ваш экстрасенс (с)
Техническую поддержку оказываем тут
Наша база знаний
Offline Георгий Садофьев  
#7 Оставлено : 13 марта 2012 г. 14:50:59(UTC)
Георгий Садофьев

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

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

Поблагодарили: 31 раз в 30 постах
В чём проблема? Какая ошибка?
Можете привести пример кода с ошибкой?
Что конкретно не получается сделать?
Техническую поддержку оказываем тут
Наша база знаний
Offline Roberto1  
#8 Оставлено : 13 марта 2012 г. 15:17:12(UTC)
Roberto1

Статус: Участник

Группы: Участники
Зарегистрирован: 12.01.2012(UTC)
Сообщений: 19
Откуда: Kazan RF

Простите если пишу не ясно, вот он вопрос.

ЭЦП проверяется публичным ключом отправителя. У меня есть сертификат с сервера с публичным ключом.
У Gost3410CryptoServiceProvider вижу функцию VerifySignature, в принципе понимаю как ее использовать.

Но, как создать Gost3410CryptoServiceProvider без приватного ключа!? или куда капать.

Раньше проверка ЭЦП делалось так. Сейчас хочу сертификат брать из хранилища, а не из файла как в примере.

Код:

FileInfo fi = new FileInfo(serverCertFilePath);
                uint certLen;
                byte[] cert = new byte[fi.Length];
                using (FileStream fs = File.OpenRead(serverCertFilePath))
                {
                    certLen = (uint)fs.Read(cert, 0, (int)fi.Length);
                    fs.Close();
                }

                //hCertContext = Crypt32Wrapper.CertCreateCertificateContext(CryptoPro.CERT_ENCODING, cert, (uint)cert.Length);
                hCertContext =                   Crypt32Wrapper.CertCreateCertificateContext( CryptoPro.PKCS_7_ASN_ENCODING | CryptoPro.X509_ASN_ENCODING, cert, (uint)cert.Length);
                if (hCertContext == IntPtr.Zero)
                {
                  ...
                }
                Crypt32Wrapper.CryptAcquireContext(out hCryptoProvider, null, null, CryptoPro.TYPE, Crypt32Wrapper.CRYPT_VERIFYCONTEXT);
                IntPtr pCertInfo = (IntPtr)Marshal.ReadInt32(hCertContext, 12);
                IntPtr pSubjectPublicKeyInfo = (IntPtr)(pCertInfo.ToInt32() + 56);
                Crypt32Wrapper.CryptImportPublicKeyInfo(hCryptoProvider, CryptoPro.CERT_ENCODING, pSubjectPublicKeyInfo, out hPubKey);
                Crypt32Wrapper.CryptCreateHash(hCryptoProvider, (uint)CryptoPro.CERT_ALG_ID, IntPtr.Zero, 0, out hHash);


                byte[] buffer = encoding.GetBytes(body);
                Crypt32Wrapper.CryptHashData(hHash, buffer, buffer.Length, 0);

                byte[] verifySignature = Convert.FromBase64String(signature);
                retVal = Crypt32Wrapper.CryptVerifySignature(hHash, verifySignature, verifySignature.Length, hPubKey, null, 0);

Отредактировано пользователем 13 марта 2012 г. 15:18:12(UTC)  | Причина: Не указана

Offline Roberto1  
#9 Оставлено : 13 марта 2012 г. 19:54:21(UTC)
Roberto1

Статус: Участник

Группы: Участники
Зарегистрирован: 12.01.2012(UTC)
Сообщений: 19
Откуда: Kazan RF

Затык был только в этом:
Gost3410CryptoServiceProvider prov = (Gost3410CryptoServiceProvider)certificate2.PublicKey.Key;

Все решилось, всех благодарю, работает:

Код:
            Gost3410CryptoServiceProvider prov = (Gost3410CryptoServiceProvider)certificate2.PublicKey.Key;

            // Создаем объект для хеширования.
            HashAlgorithm myhash = HashAlgorithm.Create("GOST3411");

            using (MemoryStream stream = new MemoryStream(encoding.GetBytes(body)))
            {
                myhash.ComputeHash(stream);
            }
            //проверим
            return prov.VerifySignature(myhash.Hash, Convert.FromBase64String(signature));


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