Валидация электронных подписей на C# с использованием КРИПТО ПРО / Хабр

Валидация электронных подписей на C# с использованием КРИПТО ПРО / Хабр Электронная цифровая подпись

Введение

Внедрение электронной подписи (без разделения на используемые криптоалгоритмы и критерий «квалифицированности», см. закон

, ст. 5) в информационную систему обычно вызвано необходимостью контроля целостности и авторства порождаемых в системе информационных потоков и документов.

Под катом описаны интерфейсы для работы с электронной подписью, а также распространенные форматы электронной подписи.

Согласно общепринятой терминологии, электронная подпись – это реквизит электронного документа, позволяющий установить факт целостности электронного документа и проверить принадлежность подписи владельцу открытого ключа подписи. Отдельно следует отметить, что электронная подпись никак не связана с конфиденциальностью информации. То есть подписанный документ все еще остается свободным для прочтения.

Электронная подпись реализуется на основе асимметричной криптографии, или криптографии с открытым ключом. Асимметричные криптографические алгоритмы предполагают использование пары ключей: открытого и закрытого. Закрытый ключ служит для выработки электронной подписи, открытый – для ее проверки.

Отдельное внимание в вопросе работы с электронной подписью следует уделить установлению соответствия между открытым ключом подписи и непосредственно лицом, которому он принадлежит. Для решения данной задачи существует такое понятие, как «Сертификат открытого ключа электронной подписи» (или просто «цифровой сертификат»).

Для выдачи, проверки действительности, отзыва и управления сертификатами необходима инфраструктура открытых ключей (Public Key Infrastructure). Вопрос сопоставления открытого ключа и его владельца – один из самых важных и сложных при работе с асимметричной криптографией, так как открытый ключ – это никак не идентифицируемый набор публичной информации, которая служит для проверки электронной подписи.

1] через проводник

Прежде всего, откройте проводник Windows и перейдите в папку, в которой сохранена ваша программа.


Нажмите правой кнопкой мыши файл установки и выберите Свойства.

Перейдите на вкладку, которая помечена как Цифровые подписи.

Если в списке подписи вы видите записи, это означает, что ваш файл имеет цифровую подпись.


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

Следовательно, вы можете знать, подписан ли файл оригинальным распространителем программного обеспечения или нет.

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

Проверка подписи

Даже если не вникать в схему, понятно, что такой алгоритм сложнее. Кроме того, нигде уже не используется простой модуль, его сменили эллиптические кривые. Эллиптическая кривая — это кривая, которая задана кубическим уравнением и имеет невообразимо сложное представление.

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

2] использование утилиты сертификатов digicert

Используйте эту ссылку , чтобы загрузить последнюю версию DigiCert и запустить исполняемый файл.

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


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

Это приведет к тому, что DigiCert проверит подпись и отобразит всю информацию в новом открывшемся окне.

DigiCert проверяет две вещи. Они заключаются в следующем:

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


Если вы получили две зеленые галочки, как показано на скриншоте выше, проверка прошла успешно. У вас есть дополнительная информация в этом окне для вашего удобства.

Microsoft crypto api 2.0

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

С целью унификации доступа к криптографическим функциям компания Microsoft разработала проприетарный API: Microsoft Crypto API. Широкое распространение приобрела версия Crypto API 2.0. Парадигма Microsoft Crypto API базируется на использовании так называемых криптопровайдеров, или, по-русски, поставщиков криптографии.

Спецификация Crypto API описывает набор функций, которые должна предоставлять библиотека криптопровайдера операционной системе, способы интеграции с ней и спецификации вызовов. Таким образом, производитель СКЗИ, выполняющий правила Crypto API, имеет возможность интеграции своего решения в операционную систему Microsoft Windows, а прикладное программное обеспечение получает доступ криптографическим функциям посредством унифицированного интерфейса.

Дополнительным плюсом является то, что компания Microsoft реализовала над Crypto API довольно большое количество функций, отвечающих за выполнение прикладных задач: работа с сертификатами, формирование различных видов подписи, работа с ключевой информацией и пр. Также Crypto API, как нетрудно догадаться, тесно интегрирован с операционной системой и ее внутренними механизмами.

Но расплатой за удобство становится платформозависимость и необходимость тесной интеграции решения в операционную систему.

В Windows Vista Microsoft представила новую версию криптографического программного интерфейса – Microsoft CNG (Cryptography API: Next Generation). Данный интерфейс базируется уже не на поставщиках криптографии, а на поставщиках алгоритмов и поставщиках хранилищ ключевой информации.

Pkcs#11

PKCS#11 (Public-Key Cryptography Standard #11) – платформонезависимый программный интерфейс для работы с аппаратно реализованными СКЗИ: смарт-карты, HSM’ы, криптографические токены. Иногда PKCS#11 используется для доступа к программно реализованным криптографическим библиотекам.

PKCS#11 представляет собой довольно обширный документ, опубликованный RSA Laboratories, который описывает набор функций, механизмов, алгоритмов и их параметров для работы с криптографическими устройствами или библиотеками. В данном документе четко прописаны правила, в соответствии с которым будет работать прикладное программное обеспечение при вызове криптографических функций.

Данный стандарт поддерживается во многих open source-проектах, использующих криптографию. Для примера, Mozilla Firefox позволяет хранить сертификаты и закрытые ключи для аутентификации через SSL/TLS на токенах, работая с ними по PKCS#11.

Если прикладное программное обеспечение «умеет» работать с PKCS#11, то производителю СКЗИ необходимо реализовать программную библиотеку, которая наружу будет выставлять интерфейсы, описанные в стандарте, а внутри реализовывать необходимую СКЗИ логику: работа непосредственно с криптографическим устройством или реализация необходимых криптоалгоритмов программно.

В этом случае прикладное программное обеспечение должно «подцепить» необходимую библиотеку и выполнять необходимые действия в соответствии с рекомендациями стандарта. Это обеспечивает заменяемость различных устройств и их библиотек для прикладного программного обеспечения и прозрачное использование СКЗИ в различных системах.

Единственным существенным минусом PKCS#11 является отсутствие рекомендаций по работе с сертификатами открытого ключа, что предполагает либо использование проприетарных расширений стандарта, либо использование других средств для работы с сертификатами.

Pkcs#7

PKCS#7 (Public-Key Cryptography Standard #7), или CMS (Cryptographic Message Syntax) – стандарт, публикуемый и поддерживаемый все той же RSA Laboratories, описываемый синтаксис криптографических сообщений.

PKCS#7 также публикуется в качестве RFC с номером 2315.

Читайте также:  Электронная подпись - НП "МосГорУслуга"

Синтаксис CMS описывает способы формирования криптографических сообщений, в результате чего сообщение становится полностью самодостаточным для его открытия и выполнения всех необходимых операций.

С этой целью в PKCS#7 размещается информация об исходном сообщении (опционально), алгоритмах хеширования и подписи, параметрах криптоалгоритмов, времени подписи, сертификат ключа электронной подписи, цепочка сертификации и т. д.

Большинство атрибутов PKCS#7 являются опциональными, но их обязательность может определяться прикладной системой.

Отдельно следует отметить, что PKCS#7 позволяет ставить несколько подписей под одним документом, сохраняя всю необходимую информацию в сообщении.

Формирование и проверка PKCS#7 реализованы в криптографических «надстройках» в Microsoft Crypto API, речь о которых шла выше. Но сам формат довольно хорошо специализирован и его поддержка может быть реализована нативно.

Roadmap

Это пятый урок из цикла «Погружение в крипту». Все уроки цикла в хронологическом порядке:

  • Урок 1. Исторические шифры. Основы и исторические шифраторы. Как работают (и анализируются) шифры сдвига, замены, Рихарда Зорге, шифр Вернама и шифровальные машины
  • Урок 2. Распределение ключей. Что это такое, как выполняется распределение ключей и как выбрать криптостойкий ключ
  • Урок 3. Современные отечественные шифры. Что такое сеть Фейстеля и какими бывают отечественные блочные шифры, используемые в современных протоколах, — ГОСТ 28147—89, «Кузнечик»
  • Урок 4. Современные зарубежные шифры. В чем разница между 3DES, AES, Blowfish, IDEA, Threefish от Брюса Шнайера и как они работают
  • Урок 5. Электронная подпись. Виды электронных подписей, как они работают и как их использовать (ты здесь)
  • Урок 6. Квантовая криптография. Что это такое, где используется и как помогает в распределении секретных ключей, генерации случайных чисел и электронной подписи

Валидация электронных подписей на c# с использованием крипто про

Продолжая разговор на тему электронных подписей (далее ЭП), надо сказать о проверке. В предыдущей стать я разбирал более сложную часть задачи — создание подписи. В этой статье всё несколько проще. Большая часть кода это адаптация примеров из КРИПТО ПРО .NET SDK. Проверять будем в первую очередь подписи по ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2021, для этого нам и нужен КРИПТО ПРО.

Задача для нас разбивается на 3 части: отделённая подпись, подпись в PDF и подпись в MS Word.

Проверка отделённой подписи:

            //dataFileRawBytes - массив байт подписанного файла
            ContentInfo contentInfo = new ContentInfo(dataFileRawBytes);
            SignedCms signedCms = new SignedCms(contentInfo, true);
            //signatureFileRawBytes - массив байт подписи
            signedCms.Decode(signatureFileRawBytes);

            if (signedCms.SignerInfos.Count == 0)
            {
                //обработка в случае отсутствия подписей
            }

            foreach (SignerInfo signerInfo in signedCms.SignerInfos)
            {
                //получаем дату подписания
                DateTime? signDate =
                    (signerInfo.SignedAttributes
                            .Cast<CryptographicAttributeObject>()
                            .FirstOrDefault(x => x.Oid.Value == "1.2.840.113549.1.9.5")
                            ?.Values[0]
                        as Pkcs9SigningTime)?.SigningTime;
                bool valid;
                try
                {
                    signerInfo.CheckSignature(true);
                    valid = true;
                }
                catch (CryptographicException exc)
                {
                    valid = false;
                }

                //получаем сертификат для проверки. Пригодится при проверке сертификата
                X509Certificate2 certificate = signerInfo.Certificate;

Комментарии все в коде, обращу только ваше внимание на получение сертификата, он нам понадобиться далее, т.к. сертификат мы будем проверять отдельно.

Ну и не забываем оборачивать всё в try-catch и прочие using. В примере я этого намеренно не делаю, что бы сократить объём

Валидация подписи в PDF. Тут нам понадобиться iTextSharp (актуальная версия на момент написания 5.5.13):

            using (MemoryStream fileStream = new MemoryStream(dataFileRawBytes))
            using (PdfReader pdfReader = new PdfReader(fileStream))
            {
                AcroFields acroFields = pdfReader.AcroFields;
                //получаем названия контейнеров подписей
                List<string> signatureNames = acroFields.GetSignatureNames();
                if (!signatureNames.Any())
                {
                    //обработка отсутствия ЭП
                }

                foreach (string signatureName in signatureNames)
                {
                    //далее следует магия получения подписи из контейнера
                    PdfDictionary singleSignature = acroFields.GetSignatureDictionary(signatureName);
                    PdfString asString1 = singleSignature.GetAsString(PdfName.CONTENTS);
                    byte[] signatureBytes = asString1.GetOriginalBytes();

                    RandomAccessFileOrArray safeFile = pdfReader.SafeFile;

                    PdfArray asArray = singleSignature.GetAsArray(PdfName.BYTERANGE);
                    using (
                        Stream stream =
                            new RASInputStream(
                                new RandomAccessSourceFactory().CreateRanged(
                                    safeFile.CreateSourceView(),
                                    asArray.AsLongArray())))
                    {
                        using (MemoryStream ms = new MemoryStream((int)stream.Length))
                        {
                            stream.CopyTo(ms);
                            byte[] data = ms.GetBuffer();
                            ContentInfo contentInfo = new ContentInfo(data);
                            SignedCms signedCms = new SignedCms(contentInfo, true);
                            signedCms.Decode(signatureBytes);
                            bool checkResult;
                            //получили подпись и проверяем её, без проверки сертификата
                            try
                            {
                                signedCms.CheckSignature(true);
                                checkResult = true;
                            }
                            catch (Exception)
                            {
                                checkResult = false;
                            }

                            foreach (SignerInfo signerInfo in signedCms.SignerInfos)
                            {
                                //получаем дату подписания
                                DateTime? signDate = (signerInfo.SignedAttributes
                                        .Cast<CryptographicAttributeObject>()
                                        .FirstOrDefault(x =>
                                            x.Oid.Value == "1.2.840.113549.1.9.5")
                                        ?.Values[0]
                                    as Pkcs9SigningTime)?.SigningTime;
                                //получаем сертификат
                                X509Certificate2 certificate = signerInfo.Certificate;
                            }
                        }
                    }
                }
            }

Комментировать опять же особенно нечего. Разве что надо сказать о Oid «1.2.840.113549.1.9.5» — это Oid даты подписания.

И последний в нашем списке это docx, пожалуй самый простой вариант:

            using (MemoryStream fileStream = new MemoryStream(dataFileRawBytes))
            using (Package filePackage = Package.Open(fileStream))
            {
                PackageDigitalSignatureManager digitalSignatureManager =
                    new PackageDigitalSignatureManager(filePackage);
                if (!digitalSignatureManager.IsSigned)
                {
                    //обрабатываем ситуацию отсутствия подписей
                }

                foreach (PackageDigitalSignature signature in
                    digitalSignatureManager.Signatures)
                {
                    DateTime? signDate = signature.SigningTime;
                    bool checkResult = signature.Verify() == VerifyResult.Success;
                    //обратите внимание на способ получения сертификата
                    X509Certificate2 certificate =
                        new X509Certificate2(signature.Signer);
                }
            }

Теперь будем разбирать сертификат и валидировать всю цепочку сертификатов. Поэтому сборка должна работать из под пользователя, у которого есть доступ в сеть.

И тут начинается ад, т.к. я не знаю как получить информацию о владельце сертификата через Oid, поэтому буду парсить строку. Смейтесь громче: цирк начинается.

А если серьёзно, то милости прошу в комменты тех, кто знает как сделать это через Oid-ы:

        private static void FillElectronicSignature(X509Certificate2 certificate)
        {
            foreach (KeyValuePair<string, string> item in ParseCertificatesSubject(certificate.Subject))
            {
                switch (item.Key)
                {
                    case "C":
                        string certificatesCountryName =
                            item.Value;
                        break;
                    case "S":
                        string certificatesState =
                            item.Value;
                        break;
                    case "L":
                        string certificatesLocality =
                            item.Value;
                        break;
                    case "O":
                        string certificatesOrganizationName =
                            item.Value;
                        break;
                    case "OU":
                        string certificatesOrganizationalUnitName =
                            item.Value;
                        break;
                    case "CN":
                        string certificatesCommonName =
                            item.Value;
                        break;
                    case "E":
                        string certificatesEmail =
                            item.Value;
                        break;
                    case "STREET":
                        string certificatesStreet =
                            item.Value;
                        break;
                    //тут интересный момент, если Window русскоязычный, то КРИПТО ПРО вернёт ИНН, а если англоязычный, то INN
                    //именно тут начиналась не пойми что после deploy на тестовый стенд
                    //локально работает, на тестовом - нет
                    case "ИНН":
                    case "INN":
                    case "1.2.643.3.131.1.1":
                        string certificatesInn =
                            item.Value;
                        break;
                    //аналогично предыдущему
                    case "ОГРН":
                    case "OGRN":
                    case "1.2.643.100.1":
                        string certificatesOgrn =
                            item.Value;
                        break;
                    //аналогично предыдущему
                    case "СНИЛС":
                    case "SNILS":
                    case "1.2.643.100.3":
                        string certificatesSnils =
                            item.Value;
                        break;
                    case "SN":
                        string certificatesOwnerLastName =
                            item.Value;
                        break;
                    case "G":
                        string certificatesOwnerFirstName =
                            item.Value;
                        break;
                    //тут рекомендую добавить блок default и всё что не удалось определить ранее писать в лог
                }
            }
            DateTime certificateNotBefore =
                certificate.NotBefore;
            DateTime certificateNotAfter =
                certificate.NotAfter;
            string certificatesSerialNumber =
                certificate.SerialNumber;

            
            if (!certificate.Verify())
            {
                //строим цепочку сертификатов
                using (X509Chain x509Chain = new X509Chain())
                {
                    x509Chain.Build(certificate);
                    //получаем все ошибки цепочки
                    X509ChainStatus[] statuses = x509Chain.ChainStatus;
                    //собираем все флаги ошибок в один int, так проще хранить
                    int certificatesErrorCode =
                        statuses.Aggregate(X509ChainStatusFlags.NoError,
                            (acc, chainStatus) => acc | chainStatus.Status, result => (int)result);
                }
            }
        }

        /// <summary>
        /// Разобрать строку с данными о владельце сертификата
        /// </summary>
        private static Dictionary<string, string> ParseCertificatesSubject(string subject)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();

            //количество двойных кавычек, для определения конца значения
            int quotationMarksCount = 0;
            //признак что сейчас обрабатывается "ключ или значение"
            bool isKey = true;
            //переменная для сбора ключа
            string key = string.Empty;
            //Переменная для сбора значения
            string value = string.Empty;

            for (int i = 0; i < subject.Length; i  )
            {
                char c = subject[i];
                if (isKey && c == '=')
                {
                    isKey = false;

                    continue;
                }
                if (isKey)
                    key  = c;
                else
                {
                    if (c == '"')
                        quotationMarksCount  ;

                    bool isItemEnd = (c == ',' && subject.Length >= i   1 && subject[i   1] == ' ');
                    bool isLastChar = subject.Length == i   1;

                    if ((isItemEnd && quotationMarksCount % 2 == 0) || isLastChar)
                    {
                        if (isItemEnd)
                            i  ;
                        if (isLastChar)
                            value  = c;
                        isKey = true;
                        if (value.StartsWith(""") && value.EndsWith("""))
                            value = value.Substring(1, value.Length - 2);
                        value = value.Replace("""", """);
                        result.Add(key, value);
                        key = string.Empty;
                        value = string.Empty;
                        quotationMarksCount = 0;

                        continue;
                    }
                    value  = c;
                }
            }

            return result;
        }

Код максимально сокращён, для лучшего понимания сути.

Читайте также:  Получение электронной цифровой подписи (ЭЦП) в Евпатории

В общем это всё, жду комментариев по получению Oid-ов из сертификата и любой аргументированной критики.

Встраивание электронной подписи в прикладные системы

Криптостойкие алгоритмы, принятые в качестве национальных или мировых стандартов, являются общедоступными. Их криптостойкость базируется на неразрешимых за приемлемое время математических задачах.

Но реализация криптоалгоритмов с учетом высокого быстродействия, отсутствия ошибок и гарантированного выполнения требований математических преобразований – непростая задача, которой занимаются квалифицированные разработчики.

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

В «западном» мире широко используется сертификация решений на соответствие Common Criteria, в России процесс сертификации средств криптографической защиты проводит ФСБ России.

Дополнительно, средства криптографической защиты информации (СКЗИ, этот термин широко используется в РФ) могут иметь самое разное представление: от программных библиотек до высокопроизводительных специализированных железок (Hardware Security Module, HSM).

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

С целью совместимости различных реализаций, а также упрощения их встраивания в прикладное программное обеспечение, были разработаны несколько стандартов, относящиеся к различным аспектам работы с СКЗИ и непосредственно электронной подписью.

Дискретное логарифмирование

Это вторая сложная проблема, на которой основаны цифровые подписи. Для начала хорошо бы усвоить, что такое дискретный логарифм. Для кого-то такое словосочетание может звучать пугающе, но на самом деле это одна из самых простых для понимания вещей в этой статье.

Предположим, дано уравнение 4x = 13 (mod 15). Задача нахождения x и есть задача дискретного логарифмирования. Почему же она так сложна для вычисления? Попробуй решить это уравнение перебором! Компьютер, ясное дело, будет более успешен, но и задачи дискретного логарифмирования обычно далеко не так просты. Возьмем для примера схему Эль-Гамаля.

Как и чем открыть файл sig расширения

Зависит от типа файла. Если файл такого расширения был прислан как вложение к электронному письму, значит, он содержит информацию об отправителе, контактные данные, имя, иногда должность и наименование подразделения. В таком случае файлы открывают почтовые сервисы. На windows это:

Чем открыть формат SIG на Mac OS:

• QUALCOMM Eudora;

Еще одна разновидность SIG – файлы программных продуктов компании Broderbund. Это разновидность ЭЦП, которая используется для графических изображений, произведенных программами компании. Метки на плакатах и баннерах – это как раз расширение SIG. Чем открыть:

  • The Print Shop
  • The Print View
  • Print Master

Статья – проверка электронной цифровой подписи authenticode. часть 1. теория

1.4. Терминология, алгоритм подписания и проверки.

1.4.1. Что такое Authenticode (Code signing).
Authenticode” (или «Code signing») означает, что сертификат предназначен для подписания кода, иначе говоря, программ и скриптов, а не документов, электронных писем, http интернет пакетов и тому подобного.

К файлам, содержащим код, относят такие форматы, как PE (.exe, .dll, .ocx, .sys, …), VBScript (.vbs), JScript (.js), Cabinet-архивы (.cab), элементы панели управления (.cpl) и некоторые другие.

Рассмотрим поближе такие понятия как: хеш, алгоритм хеша, подпись, сертификат, отпечаток, выборка и т.п. (часть информации взята из ответов участников конференции StackExchange CBHacking и Tom Leek (в переводе, с авторской переработкой и дополнениями)).

1.4.2. Что такое хеш.

Хеш – это значение фиксированной длины, которое получено после выполнения набора арифметических операции над строкой, файлом или другим блоком данных. Грубо говоря, мы подаём на вход длинную строку, затем берём код каждого символа этой строки, складываем по определённому принципу (называемому алгоритмом хеша), и в результате получаем значение, обычно записываемое в 16-ричном виде.

Вот примеры наиболее распространённых хешей:

Подробную таблицу сравнительных характеристик SHA вы можете посмотреть на wiki

здесь

и

здесь

.

Программно рассчитывать хеш можно, например, через CryptoAPI (пример) или Cryptography API: Next Generation (CNG) (пример).

1.4.3. Что такое выборка (дайджест).
Выборка (digest) – обычно подразумевает, что мы берём данные не целиком, а избирательно, только какую-то часть, которая и называется выборкой. Расположение этой части зависит от структуры данных и вида алгоритма, для которого эта выборка используется.

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

1.4.4. Что такое приватный и публичный ключи, симметричное и асимметричное шифрование.

Представьте себе шифрование по алгоритму Цезаря, где код каждого символа строки сдвигается на некоторое одинаковое количество пунктов (например, вперёд по алфавиту). Здесь ключом является – количество пунктов сдвига.

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

Существуют и так называемые асимметричные алгоритмы, например, RSA. Здесь ключи для шифрования и дешифровки – разные. Т.е. ключ шифрования не подходит для расшифровки, и наоборот. Кроме того, невозможно рассчитать ключ шифрования, если у вас есть ключ дешифровки.

Представьте, что вам дали сообщение, зашифрованное ключом (он называется – приватный). Вы знаете, по какому принципу происходит шифрование, и у вас даже есть ключ (публичный), которым можно расшифровать сообщение. Но с помощью этого же ключа у Вас не получится снова зашифровать исходное сообщение, чтобы получить такую же шифро-фразу, потому как результат уже не расшифруется тем же ключом. Такова особенность асимметричных алгоритмов. Подробнее о них вы можете почитать в протоколе Диффи-Хеллмана-Меркла или посмотреть это видео:

Приватный ключ ещё называют закрытым (или секретным).

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

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

В контексте подписания и проверки цифровых подписей шифрование всего сообщение не нужно и не требуется. Вместо этого, RSA накладывается на хеш сообщения.

Итоговая схема:
ФАЙЛ => выборка => хеш приватный ключ => шифрованный хеш.

1.4.5. Что такое сертификат, центр сертификации и цепочка доверия.

Сертификат связывает личность (издателя) с публичным ключом (который где-то имеет соответствующий приватный ключ). Сперва вы признаёте, что сертификат действителен – то есть содержащийся в нём ключ действительно принадлежит лицу или организации, которое он идентифицирует. Для защиты от подделки сертификаты также подписываются цифровой подписью.

Читайте также:  ЭЦП для госторгов, получить электронную подпись (сертификат) для участия в госзакупках

Центр сертификации – это объект (обычно, организация), которой доверено выдавать сертификаты, утверждающие, что индивидуальный получатель, компьютер или организация, запрашивающие сертификат, выполняют условия установленной политики (подробнее: см. раздел 1.10 «Покупка сертификата»). Под политикой здесь обычно подразумевают, что центр сертификации подтвердил подлинность предоставленных получателем документов, которые его идентифицируют (имя, место проживания и т.п.).

Сертификат может быть подписан не напрямую центром сертификации, а промежуточным звеном, которому Центр предоставил права выдавать сертификаты. Это называется цепочкой доверия. Её можно проследить, изучив цифровую подпись сертификата:

Сертификат считается легитимным, если он подписан (закрытым) ключом, соответствующим (публичному ключу) сертификата, которому вы доверяете. Соответственно, в цепочке доверия к самому первому (корневому) сертификату звена у вас должны быть установлены отношения доверия (в контексте исполняемых файлов Windows это означает, что такой сертификат должен быть помещён в корневое хранилище – см. подробнее далее в разделе 1.5.).

1.4.6. Форматы файлов сертификатов и ключей для Authenticode подписи и их преобразование.

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

PKCS # 12 и PKCS # 7

– это международные спецификации криптографии с открытым ключом.

Формат X.509 (его ещё называют сертификатом открытого ключа). Он состоит из таких частей:

Внутри каждого сертификата формата X.509 хранится пара Distinguished Names (DN) в формате X.500. Один DN принадлежит владельцу сертификата, а второй DN указывает идентификатор CA, подписавшей сертификат. В случае с self-signed сертификатом, оба эти DN указывают на владельца сертификата.

Distinguished Name задается в виде разделенных через запятую атрибутов, например:

«CN=Andrey Chesnokov, OU=dev64, O=dev64-wordpress, L=Unknown, ST=Unknown, C=RU»
«C=RU, PostalCode=115093, S=Moscow, L=Moscow, STREET=”Street Serpukhovsko B, 44″, O=RIVER SOLUTIONS, CN=RIVER SOLUTIONS»

Здесь отдельные атрибуты расшифровываются так:

CN — common name (уникальное имя владельца)

L — localityName (местоположение: город)

ST — stateOrProvinceName (название штата или провинции)

O — organizationName (имя организации)

OU — organizationUnit, department or division (департамент или отдел)

C — country, two-letter country code (двухбуквенный код страны)

STREET = streetAddress (адрес: улица)

DC = domainComponent (метка доменного имени)

UID = userid (идентификатор пользователя)

Часть из атрибутов может быть пропущено, например, присвоено значение Unknown.
Формат строки описан в RFC2253 и RFC1779.

Подробнее о внутренней структуре формата сертификата X.509 можно почитать в статьях:
X.509 — Википедия
Разбираем x.509 сертификат
Структура PKCS7-файла
RFC5280

Microsoft PVK – является недокументированным форматом, однако кое-что о его структуре можно почитать в этой заметке:
PVK file format

Примечательно, что на этапе генерации пары ключей, вам необходимо будет ввести пароль. Это дополнительная мера защиты. Приватный ключ шифруется одним из алгоритмов – 3DES, RC4 или RC2. Без знания пароля потенциальный злоумышленник, выкравший файл сертификата, не сможет воспользоваться приватным ключом.

б) Преобразование форматов.

Иногда возникает необходимость сконвертировать форматы сертификатов из одного в другой. Для этих целей вам могут пригодиться такие инструменты из состава Windows SDK, как pvk2pfx.exe, cert2spc.exe, а также openssl.

Примеры конвертации:

Некоторые другие примеры командной строки преобразования форматов можно посмотреть в

этой базе знаний Symantec

.

Выше рассмотрены только сертификаты для подписания кода. Так, следует заметить, что например, для SSL-сертификатов существуют и другие форматы, например, .jks – Java Key Stroke – это хранилище открытых и закрытых ключей и сертификатов. Работать с ним можно с помощью инструмента keytool из состава Java Runtime Environment.

Пример для JKS -> DER см. в моей заметке: Как получить ЭЦП для подписания документов (для жителей Украины).

Вот ещё часть примеров для демонстрации возможностей openssl (взято отсюда):

Сырая подпись

Описанные выше форматы электронной подписи необходимы при взаимодействии разнородных систем, когда информация об отправителе подписанного сообщения минимальна.

При взаимодействии в рамках одной информационной системы, когда информация об отправителе, используемых криптоалгоритмах и их параметрах известна получателю, более рационально использование «сырой» электронной подписи.

В этом случае фактически передается только само значение электронной подписи вместе с документом. Информация для проверки берется получателем из централизованной базы данных.

Это позволяет значительно упростить процедуры выработки и проверки подписи, так как отсутствуют шаги формирования и разбора сообщений в соответствии с каким-либо форматом.

Форматы электронной подписи

Описанные выше интерфейсы для доступа к криптографическим функциям позволяют обращаться за выполнением математических преобразований к различным, как хорошо было замечено Microsoft, «поставщикам криптографии».

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

Цифровая подпись в bitcoin

Помимо прочего, электронная подпись используется в криптовалютах, в частности — в Bitcoin. У каждого пользователя Bitcoin есть пара из секретного и открытого ключа. Хеш-значение открытого ключа служит основным адресом для передачи монет. Это значение не секретно, и сообщать его можно кому угодно. Но по значению хеша вычислить значение открытого ключа невозможно.

Сама пара ключей будет использована лишь однажды — при передаче прав собственности. На этом жизнь пары ключей заканчивается.

  • PUB1 — публичный ключ;
  • PRIV1 — секретный ключ;
  • HASH1 или HASH(PUB1) — хеш-значение открытого ключа (биткойн-адрес);
  • HASH2 или HASH(PUB2) — хеш открытого ключа следующего владельца.

Вот как устроен сам процесс передачи прав собственности на биткойны.

  1. Владелец монеты открыто сообщает хеш своего публичного ключа HASH(PUB1), это и будет идентифицировать биткойн.
  2. До момента продажи оба ключа PUB1, PRIV1 продавца остаются в секрете. Известен только HASH(PUB1) и соответствующий ему биткойн.
  3. Как только появляется покупатель, владелец формирует открытое письмо, в котором указывает адрес биткойна HASH(PUB1) и хеш-значение публичного ключа нового владельца HASH(PUB2). И конечно же, подписывает письмо своим секретным ключом PRIV1, прилагая публичный ключ PUB1.
  4. После этого пара ключей владельца PUB1 и PRIV1 теряют свою актуальность. Публичным ключом можно проверить само письмо, узнать новый адрес монеты.

О втором собственнике ничего не известно, кроме HASH(PUB2), до тех пор пока он не передаст права третьему владельцу. И эта цепочка может быть бесконечной.

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

Благодаря HASH(PUB) получается двойная защита. Первая загадка — узнать публичный ключ по его хешу. Вторая загадка — подписаться чужим секретным ключом.

Такая технология построения цепи передачи прав и называется блокчейном. Благодаря этой технологии можно отследить историю владения до самых истоков, но изменить эту историю никак нельзя.

Оцените статью
ЭЦП Эксперт
Добавить комментарий