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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline SukhovPro  
#1 Оставлено : 5 декабря 2008 г. 14:28:06(UTC)
SukhovPro

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

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

Сори за новый топик.
Я парвильно понял, вот из примера:
Код:

        static public byte[] SignMsg(
            Byte[] msg,
            X509Certificate2Collection signerCerts,
            X509Certificate2Collection countersignerCerts)
        {
            //  В коллекции должен быть хотя бы один сертификат.
            if (signerCerts.Count == 0 || countersignerCerts.Count == 0)
            {
                throw new ArgumentOutOfRangeException("Empty certificate" +
                    " collection passed to SignMsg.");
            }

            // Помещаем сообщение в объект ContentInfo.
            // Это нужно, чтобы постороить объект SignedCms.
            ContentInfo contentInfo = new ContentInfo(msg);

            SignedCms signedCms = new SignedCms(contentInfo);

            // Подписываем сообщение в формате CMS/PKCS7
            // один раз для каждого сертификата отправителя.
            foreach (X509Certificate2 cert in signerCerts)
            {
                Console.Write("Computing signature with signer subject " +
                    "name {0} ... ", cert.SubjectName.Name);
                signedCms.ComputeSignature(new CmsSigner(cert));
                Console.WriteLine("Done.");
            }

     
            // Вычисляем дополнительную подпись к первой в сообщении в формате
            // CMS/PKCS7 один раз для каждого сертификата дополнительной подписи.
            foreach (X509Certificate2 cert in countersignerCerts)
            {
                Console.Write("Computing countersignature with signer " +
                    "subject name {0} ... ",
                    cert.SubjectName.Name);
                signedCms.SignerInfos[0].ComputeCounterSignature(new
                    CmsSigner(cert));
                Console.WriteLine("Done.");
            }

            // Кодируем сообщение в формате CMS/PKCS7
            return signedCms.Encode();
        }


Я получаю масив байт который просто напрямую
пишу в файл и подключаю открепленную ЭЦП формата PKCS7.
И другим стандартным ПО можно будет проверять эту ЭЦП, кстати не подскажете какое свободное ПО есть для такой проверки. Просто интересно протестировать верность формата, того что написал в открепленный файл.

Offline Челпанов А.  
#2 Оставлено : 5 декабря 2008 г. 17:31:24(UTC)
Челпанов А.

Статус: Активный участник

Группы: Участники
Зарегистрирован: 24.12.2007(UTC)
Сообщений: 390
Мужчина
Откуда: КриптоПро

Поблагодарили: 2 раз в 2 постах
Пример, котрый вы привели в тексте сообщения демонстрирует один из вариантов установки нескольких подписей на документ - Countersigner и это скорее всего не то что Вам требуется (в этом примере подписанный документ содержит как сам документ так и его подпись).
Открепленная подпись создается почти так же как и совмещенная с сообщением, за исключение создания класса SignedCms. В кострукторе необходимо указать, что создается открепленная подпись:
Код:
SignedCms signedCms = new SignedCms(contentInfo, true);

Проверка подписи так же аналогична, за исключением того, что при создании объекта SignedCms необходимо передать как сообщения так и флаг detached подписи, например, так
Код:
ContentInfo contentInfo = new ContentInfo(msg);
SignedCms signedCms = new SignedCms(contentInfo, true);


Пример кода для получения открепленной подписи:
Код:
class DetachedSignature
{
    const String signerName = "TestGost";

    [STAThread]
    static void Main(string[] args)
    {
        //  Исходное сообщение.
        const String msg = "Это сообщение, которое будет подписано.";

        Console.WriteLine("\nИсходное сообщение (длина {0}): {1}  ",
            msg.Length, msg);

        //  Переводим исходное сообщение в массив байтов.
        Encoding unicode = Encoding.Unicode;
        byte[] msgBytes = unicode.GetBytes(msg);

        Console.WriteLine("\n\n------------------------------");
        Console.WriteLine(" Поиск сертификата            ");
        Console.WriteLine("------------------------------\n");

        X509Certificate2 signerCert = GetSignerCert();

        Console.WriteLine("\n\n----------------------");
        Console.WriteLine("На стороне отправителя");
        Console.WriteLine("----------------------\n");

        byte[] encodedSignature = SignMsg(msgBytes, signerCert);

        Console.WriteLine("\n\n------------------------");
        Console.WriteLine(" На стороне получателя  ");
        Console.WriteLine("------------------------\n");

        // При проверка detached подписи передаем и само сообщение
        if (VerifyMsg(msgBytes, encodedSignature))
        {
            Console.WriteLine("\nСообщение проверено.");
        }
        else
        {
            Console.WriteLine("\nОшибка при проверке сообщения.");
        }
    }

    //  Открываем хранилище 'My' и ищем сертификат
    //  для подписи сообщения. Сертификат должен 
    //  иметь поля Субъект (subject name) "TestGost".
    static public X509Certificate2 GetSignerCert()
    {
        //  Открываем хранилище My.
        X509Store storeMy = new X509Store(StoreName.My,
            StoreLocation.CurrentUser);
        storeMy.Open(OpenFlags.ReadOnly);

        //  Отображаем сертификаты для удобства работы
        //  с примером.
        Console.WriteLine("Найдены сертификаты следующих субъектов " +
            "в хранилище {0}:", storeMy.Name);
        foreach (X509Certificate2 cert in storeMy.Certificates)
        {
            Console.WriteLine("\t{0}", cert.SubjectName.Name);
        }

        //  Ищем сертификат для подписи.
        X509Certificate2Collection certColl =
            storeMy.Certificates.Find(X509FindType.FindBySubjectName,
            signerName, false);
        Console.WriteLine(
            "Найдено {0} сертификат(ов) в хранилище {1} для субъекта {2}",
            certColl.Count, storeMy.Name, signerName);

        //  Проверяем, что нашли требуемый сертификат
        if (certColl.Count == 0)
        {
            Console.WriteLine(
                "Сертификат для данного примера не найден " +
                "в хранилище. Выберите другой сертификат для подписи. ");
        }

        storeMy.Close();

        //  Если найдено более одного сертификата,
        //  возвращаем первый попавщийся.
        return certColl[0];
    }

    //  Подписываем сообщение секретным ключем.
    static public byte[] SignMsg(
        Byte[] msg,
        X509Certificate2 signerCert)
    {
        //  Создаем объект ContentInfo по сообщению.
        //  Это необходимо для создания объекта SignedCms.
        ContentInfo contentInfo = new ContentInfo(msg);

        //  Создаем объект SignedCms по только что созданному
        //  объекту ContentInfo.
        //  SubjectIdentifierType установлен по умолчанию в 
        //  IssuerAndSerialNumber.
        //  Свойство Detached устанавливаем явно в true, таким 
        //  образом сообщение будет отделено от подписи.
        SignedCms signedCms = new SignedCms(contentInfo, true);

        //  Определяем подписывающего, объектом CmsSigner.
        CmsSigner cmsSigner = new CmsSigner(signerCert);

        //  Подписываем CMS/PKCS #7 сообение.
        Console.Write("Вычисляем подпись сообщения для субъекта " +
            "{0} ... ", signerCert.SubjectName.Name);
        signedCms.ComputeSignature(cmsSigner);
        Console.WriteLine("Успешно.");

        //  Кодируем CMS/PKCS #7 подпись сообщения.
        return signedCms.Encode();
    }

    //  Проверяем SignedCms сообщение и возвращаем Boolean
    //  значение определяющее результат проверки.
    static public bool VerifyMsg(Byte[] msg, 
        byte[] encodedSignature)
    {
        //  Создаем объект ContentInfo по сообщению.
        //  Это необходимо для создания объекта SignedCms.
        ContentInfo contentInfo = new ContentInfo(msg);

        //  Создаем SignedCms для декодирования и проверки.
        SignedCms signedCms = new SignedCms(contentInfo, true);

        //  Декодируем подпись
        signedCms.Decode(encodedSignature);

        //  Перехватываем криптографические исключения, для 
        //  возврата о false значения при некорректности подписи.
        try
        {
            //  Проверяем подпись. В данном примере не 
            //  проверяется корректность сертификата подписавшего.
            //  В рабочем коде, скорее всего потребуется построение
            //  и проверка корректности цепочки сертификата.
            Console.Write("Проверка подписи сообщения ... ");
            signedCms.CheckSignature(true);
            Console.WriteLine("Успешно.");
        }
        catch (System.Security.Cryptography.CryptographicException e)
        {
            Console.WriteLine("Функция VerifyMsg возбудила исключение:  {0}",
                e.Message);
            Console.WriteLine("Проверка PKCS #7 сообщения завершилась " +
                "неудачно. Возможно сообщене, подпись, или " +
                "соподписи модифицированы в процессе передачи или хранения. " +
                "Подписавший или соподписавшие возможно не те " +
                "за кого себя выдают. Достоверность и/или целостность " +
                "сообщения не гарантируется. ");
            return false;
        }

        return true;
    }
}


Проверять совместимость лучше навтречу с тем продуктом, с которым предполагается встречная работа, т.к. кроме банальных ошибок, возможно множество всяких ньюансов. Например стандарт CMS/PKCS7 поддерживает, различные способы кодирования отправителя, которые конкретное ПО может не поддерживать.
Для проверки корректности кодирования сообщения можно использовать "Приложение командной строки dumpasn1 Питера Гутмана (Peter Gutmann) для просмотра файлов формата ASN.1 BER/DER: dumpasn1.rar (Windows, x86)." доступно на нашем сайте в разделе "Загрузка файлов".
Для проверки корректности вычисления подписи и выяснения проблем совместимости с CAPI/CSP можно использовать csptest (опции cmslowsign, cmssfsign,...) входящий в состав csp версий выше 3.0
С уважением, Александр.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.