Русский
Русский
English
Статистика
Реклама

Электронная подпись

Доверенная третья сторона как с ее появлением меняется электронная подпись

24.12.2020 18:19:54 | Автор: admin


За последние 10 лет принципиальным образом так и не решились вопросы удобного и долговременного (или еще архивного) хранения документов c электронной подписью (ЭП) и их обмена со взаимным доверием. Да, есть специальные архивные разновидности расширенных форматов ЭП (CAdES-A и XAdES-A), которые содержат несколько меток времени, списки отозванных сертификатов и цепочки удостоверяющих центров (УЦ) на момент формирования ЭП. Есть варианты решений с переподписанием документов с ЭП или созданием доверенной среды для их хранения. Однако все это не добавляет юзабилити. Появились и новые проблемы: отсутствие единой политики применения квалифицированных сертификатов в коммерческих информационных системах (особенно на торговых площадках), из-за чего в сертификаты начали добавлять узкоспециализированные OID; отсутствие единого реестра выданных сертификатов при значительном увеличении их числа; большое количество УЦ и их текучка; попытки мошенничества с недвижимостью и налоговыми декларациями при помощи квалифицированных сертификатов с ЭП, полученных мошенническим образом.

Принятые 27 декабря 2019 г. изменения в Федеральный закон Об электронной подписи нацелены на то, чтобы, наконец-то, устранить большинство этих проблем, узаконить облачную ЭП, а также фактически перестроить рынок удостоверяющих центров. Закон также вводит новый институт доверенную третью сторону (ДТС). Нормы о ДТС должны вступить в силу с 1 января 2021 года. Несмотря на это, почти все, что связано с ДТС, еще в ожидании разъяснений и регламентации со стороны регуляторов. Попробую описать подробно, что нас ждет.


Какие неочевидные проблемы краткосрочности обычной электронной подписи существуют сегодня?


Я работаю в подразделении, которое занимается прикладной интеграцией. Так сложилось, что нам не приходилось внедрять штатную ЭП для документооборота из коробки или внедрять готовые клиентские приложения для работы с ЭП. Почти всегда задачи внедрения сводились к встраиванию ЭП (включая разного рода автоматизации по обслуживанию жизненного цикла сертификатов, ключей и их носителей) в существующие и совсем не коробочные документообороты или в информационные системы, в том числе с длительным хранением документов. На первых этапах проектирования процесс формирования ЭП больших сложностей обычно ни у кого не вызывал. Казалось бы, ну что тут? Сформировать хеш на документ и подписать его закрытым ключом с использованием базовых форматов электронной подписи, например, CAdES-BES или XAdES-BES. А вот потребность в дальнейшем среднесрочном и долговременном хранение документов с ЭП, проверка ЭП в документообороте (в том числе автоматизированная) всегда в конечном итоге влияли на архитектуру решения. Усложнялись форматы ЭП, начиная от CAdES-T и XAdES-T (с метками времени) и заканчивая их расширенными и специальными A-версиями (Archival). А дальше всё по кругу возвращалось к процессу формирования ЭП, чтобы обеспечить необходимым контекстом выбранный для нее формат.

Так как осуществить проверку ЭП документа, хотя бы лет так через 10-15? (Опустим такую подробность, что, скорее всего, спустя столько лет не будет сертифицированных средств криптографической защиты информации (СКЗИ), поддерживающих нужные криптографические алгоритмы и нужные форматы, а необходимые средства просмотра электронных документов не будут запускаться на текущих ОС.)

Обратимся к закону об ЭП (от 06.04.2011 63-ФЗ). Какие условия признания (проверки) квалифицированной ЭП содержатся в статье 11 Признание квалифицированной электронной подписи (приведу только пункт 2 статьи, потому что именно он влияет на проверку документов с ЭП во времени):
Квалифицированная электронная подпись признается действительной [] при одновременном соблюдении следующих условий:

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

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

Законодатель не предложил и даже не намекнул на способы подтверждения достоверности информации о моменте подписания электронного документа. Впрочем, это нормально. Требования к процедуре должны раскрывать ответственные регуляторы. И спустя 9 лет, после того, как в конце 2019 года вышли изменения к закону об ЭП, Минцифры России и ФСБ России (в части работы с меткой времени, но об этом дальше), наконец-то, разработали проекты приказов. Пока же бремя доказывания достоверности момента подписания все еще лежит на плечах разработчиков СКЗИ и на владельцах информационных систем. Например, полагаясь на открытые международные спецификации и стандарты, они вынуждены сами выбирать форматы ЭП, в том числе с меткой времени, и ждать, подтвердит или скорректирует их подход судебная практика.

Какие решения для обхода краткосрочности базовой ЭП обычно используют?


Единый стандарт для формата ЭП с меткой времени в процессе разработки. Самым очевидным, с точки зрения среднесрочного (5-10 лет) и долгосрочного хранения документов с ЭП, является реализация квалифицированной ЭП в одном из расширенных форматов (на усмотрение владельца ИС) как минимум:

  • с внедренной меткой времени для достоверного определения момента подписания электронного документа сроком до 15 лет (теоретический максимальный срок действия сертификата ключа проверки ЭП сервиса меток времени);
  • с информацией о факте проверки сертификата в виде приложенного ответа от OCSP-службы (службы онлайн-проверки статуса сертификата) или приложенного списка отозванных сертификатов (обеспечивающего подтверждение действительности квалифицированного сертификата на момент подписания), подкрепленных меткой времени.

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

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

Как изменит ситуацию появление доверенной третьей стороны?


Мы добрались до самого главного. В дополнениях к 63-ФЗ Об электронной подписи от 27.12.2019 вместе с целым рядом изменений, в том числе юридическим признанием облачной ЭП, появляется институт доверенной третьей стороны (статья 18.1). Это новый вид организации, которая призвана обеспечить доверие при обмене электронными документами с ЭП.

Законом определяется перечень услуг, которые ДТС будут оказывать участникам электронного взаимодействия:

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

Иными словами, появляется аккредитованная организация (а не просто набор сервисов при аккредитованном УЦ), предоставляющая такой необходимый набор услуг:

  • проверка действительности ЭП и сертификатов на определенный момент времени;
  • проверка полномочий владельцев сертификатов ЭП;
  • выдача квитанций с результатами проверки квалифицированной ЭП;
  • ведение фактического реестра выполняемых (верифицируемых) операций.

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

А что не так с меткой времени и когда она должна заработать?


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

К сожалению, законодатель (до декабря 2019) и регуляторы (до сентября 2020) не раскрывали функционал метки времени. Отсюда пошли различные несовместимые между собой форматы ЭП. Они вроде бы и являлись усиленными квалифицированными и были выполнены на сертифицированных средствах, но обмен документами с такими ЭП с автоматическим доверием между разными информационными системами в обход системы межведомственного электронного взаимодействия (СМЭВ) был невозможен. В СМЭВ, конечно же, используется метка времени, выдаваемая внутренним сервисом для ЭП в формате XAdES-T, но решает она скорее транспортные задачи при передаче документов.

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

Метка доверенного времени (именно так указано в законе об ЭП, но я везде пишу просто метка времени) добавлена изменениями к закону об ЭП от 27.12.2019 г. Правда этот термин упоминается однократно в ст. 2 Основные понятия, используемые в настоящем Федеральном законе, и больше нигде не используется. Норма о метке времени вступает в силу одновременно с нормой о ДТС (с 01.01.2021 года), поскольку они связаны между собой.

Закон определяет метку времени так:
Достоверная информация в электронной форме о дате и времени подписания электронного документа электронной подписью, создаваемая и проверяемая доверенной третьей стороной, удостоверяющим центром или оператором информационной системы [].

Таким образом, метка времени может создаваться и проверяться ДТС, УЦ и оператором ИС, если она получена:
[]в момент подписания электронного документа электронной подписью в установленном уполномоченным федеральным органом порядке с использованием программных и (или) аппаратных средств, прошедших процедуру подтверждения соответствия требованиям, установленным в соответствии с настоящим Федеральным законом.

Почти год спустя (14 сентября 2020 г.) после появления метки времени в законе об ЭП вышел приказ Минцифры России 472 Об утверждении Формата электронной подписи, обязательного для реализации всеми средствами электронной подписи. Он, наконец-то:

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

Далее. В дополнение к приказу Минцифры России 472 (где, как я написал выше, нет ни определения метки времени, ни ссылки на нее, но есть требование к размещению в составе ЭП времени создания ЭП) появилось 2 проекта правовых актов:

  • приказа Министерства цифрового развития, связи и массовых коммуникаций Российской Федерации Об утверждении порядка создания и проверки метки доверенного времени в версии от 09.10.2020. Здесь раскрывается порядок создания и проверки меток времени службой меток доверенного времени (новый термин), определяются протокол взаимодействия со службой штампов времени (еще один новый термин), а также формат и содержание метки времени;
  • приказа ФСБ России О внесении изменений в приложения 1 и 2 к приказу ФСБ России от 27 декабря 2011 г. 796 Об утверждении Требований к средствам электронной подписи и Требований к средствам удостоверяющего центра. Он обязывает создавать средства, реализующие механизмы формирования меток доверенного времени и службы меток доверенного времени в составе УЦ.

Очевидно, что ДТС для фиксирования определенного момента времени также нужна метка времени или сертификат ЭП, срок действия которого еще не истек. Метка времени должна быть одновременно и доверенной, и правильной (ДТС должна ее понимать). И, скорее всего, идеальный алгоритм проверки электронных документов с ЭП, в которых реализована метка времени, в ДТС будет следующем:

  1. Создание электронного документа с ЭП, где ЭП реализована средствами и в формате с поддержкой метки времени (приказ Минцифры России 472).
  2. Получение метки времени в ДТС или где-то еще (в УЦ или у оператора ИС).
  3. Встраивание метки времени (выданной аккредитованным сервисом ДТС/УЦ/оператор ИС) в документ с ЭП.

И только если все эти этапы будут пройдены, ДТС сможет подтвердить действительность электронной подписи со всеми плюшками и расширенными отчетами. Что из этого следует? Все, кто пожелает использовать ДТС для проверки документов с ЭП после истечения срока действия сертификата ЭП, должны иметь:

  • ЭП расширенного формата (тот же приказ Минцифры России 472, в котором, повторюсь еще раз, метка времени не определена);
  • средства работы с ЭП (СКЗИ, прикладное ПО), которые поддерживают работу с метками времени (технически это может быть и отдельный файл с еще одной отсоединенной электронной подписью сервиса меток времени);
  • соблюдение алгоритма по получению метки времени и встраивания ее в документ с ЭП.

Формат метки времени
Проект приказа Минцифры России, о котором я писал выше, предлагает сделать rfc 3161 Time-Stamp Protocol (TSP) основой для формата метки времени и протокола взаимодействия со службой штампов времени. Кроме того, в документе предъявляются общие требования к алгоритму работы службы штампов времени. Вот некоторые из них:

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

Если пропустить параметры, касающиеся протокола взаимодействия вызывающей стороны со службой штампов времени, то сама метка времени TimeStampToken будет выглядеть так:

image

На ум приходит пока только пара производителей СКЗИ, которые уже выпускают средства (серверную часть, библиотеки и клиентскую часть) для работы с меткой времени по rfc3161.


Нормативно-правовые акты регуляторов еще не приняты, тем не менее пазл с меткой времен начинает сходиться:

  • есть требования к ЭП (приказ Минцифры России 472, который определяет необходимость учитывать время создания ЭП);
  • есть требования к службе и формату метки времени (проект приказа Минцифры, см. выше);
  • есть требования к СКЗИ, в которых должна поддерживаться метка времени (проект приказа ФСБ, см. выше);
  • есть требования к УЦ и ДТС, в составе которых должна быть реализована служба меток доверенного времени (тот же проект приказа ФСБ, см. выше).


Сложный функционал проверки полномочий в ДТС


Вернемся к ДТС и функционалу проверок правильности применения сертификатов ЭП и полномочий. В соответствии с изменениями в законе об ЭП от 27.12.2019 ДТС выступает в том числе в роли авторизационного центра, выполняющего:

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

При этом первый пункт также должен включать проверку правильности применения сертификата квалифицированной электронной подписи (КЭП):

  • ведомственной или организационной принадлежности УЦ, чей сертификат КЭП используется в конкретных электронных правоотношениях (правоотношения юридических лиц УЦ налоговой службы; правоотношения финансовых, кредитных организаций УЦ Центробанка; правоотношения лиц, представляющих органы государственной власти и органы местного самоуправления, УЦ Федерального казначейства; правоотношения физических лиц коммерческие аккредитованные УЦ);
  • типа сертификата квалицированной электронной подписи (физлицо, юрлицо, ИП) на правильность его применения в конкретном электронном правоотношении.

Отдельно разберемся со вторым пунктом проверкой полномочий. Кроме правильности применения типа сертификата выданного на физлицо, юрлицо или ИП, здесь должна выполняться проверка документа о полномочиях, который должен быть подписан КЭП уполномоченного в установленном порядке на принятие соответствующих решений должностного лица соответствующего государственного органа или органа местного самоуправления. Сами же полномочия должны быть определены на основании классификатора полномочий, который уполномоченный федеральный орган формирует, актуализирует. В соответствии со статьями 17.2 и 17.3 закона об ЭП необходимо также проверить наличие и содержимое электронной доверенности, поскольку именно она уполномочивает сторону на те или иные правоотношения. Таким образом, при проверке полномочий ДТС должна также проверять:

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

Выполнять данные проверки, конечно же, сможет прикладная система. Она понимает контекст электронных правоотношений, знает, какие полномочия и доверенности допустимы с сертификатами КЭП и с какими УЦ можно/нужно работать. Другой вопрос, как будет проводить такие проверки ДТС, ведь она не обладает информацией о контексте правоотношений.

Авторизационные операции при использовании сертификатов ЭП, с одной стороны, унифицировались. Специфицированные OID-ы в сертификатах ЭП теперь должны игнорироваться, а схемы авторизаций по принципу свой/чужой OID с 01.06.2020 вне закона. С другой стороны, разграничение полномочий и правила применения сертификатов ЭП трансформировались в более сложные процессы, которые еще должны быть отрегулированы к 01.01.2022.

Белые пятна в проверке полномочий
В проекте приказа ФСБ России Об утверждении Требований к средствам доверенной третьей стороны, включая требования к используемым доверенной третьей стороной средствам электронной подписи разъяснений по авторизационным функциям ДТС так и не последовало. Например, пункт 2.3 проекта требований гласит:

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


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

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


Выводы: уже куда-то бежать или ждать?


Легализация хранения и дистанционного использования средствами УЦ облачной ЭП с 01.01.2021 должна запустить новый виток ее развития. Это касается увеличения количества внедряемых услуг на базе ЭП (особенно в наше ковидное время) и удобных сервисов работы с ЭП для мобильных клиентов и клиентов на рабочих местах, которые, в свою очередь, будут нуждаться во внешних обслуживающих сервисах проверки ЭП (на базе ДТС).

Скорее всего, либо под новый год, либо сразу же после праздников упомянутые мною приказы примут. Потом разработчикам СКЗИ потребуется еще месяца 3-4 для корректировки клиентского ПО и библиотек под новый формат ЭП с меткой времени и сервисы служб меток доверенного времени. К слову, последние у ключевых разработчиков СКЗИ уже реализованы и эксплуатируются как TSP-службы штампов времени.

Далее потребуется еще некоторое время на разработку функционала ДТС, явно не завязанного на какие-либо форматы, но необходимого по закону об ЭП:

  • создание квитанций с результатом проверки КЭП в электронном документе;
  • хранение данных, в том числе документирование выполняемых ДТС операций.

С учетом всех необходимых доработок ПО, а также организационных процедур на аккредитацию, ждать появления первых ДТС раньше лета 2021 года, думаю, не стоит. Может быть, ФНС и ключевой разработчик СКЗИ выпустят что-то раньше в качестве тестовой версии ДТС.

Услуги ДТС, очевидно, не будут бесплатными для всех, и все затраты прямо или косвенно лягут на участников электронного взаимодействия.

Появление на рынке ДТС должно в итоге способствовать появлению полезных сервисов (в первую очередь, в виде API для встраивания), которые смогут обеспечивать:

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

Эти сервисы можно будет встраивать в информационные системы, например:

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

Сервисы найдут применение и в мобильных клиентах разных информационных систем, в том числе для работы с облачной ЭП. Второй вариант соответствует недавно озвученному предложению Максута Шадаева, министра цифрового развития, связи и массовых коммуникаций России:

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


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

Итого: заявленные изменения в законе об ЭП и предложенный функционал ДТС действительно интересны, долгожданны и обязательно будут востребованы. Метка времени (которая вводится одновременно с ДТС с 01.01.2021) автоматически решит проблемы среднесрочного хранения документов. ДТС и унифицированный формат ЭП с меткой времени позволят осуществлять доверенный оборот документов с ЭП старше 1 года и проверять их после отчуждения из системы. Конечно, многое зависит от реализации, и в том числе от регламентов и приказов Минцифры России и приказов ФСБ России, которые в идеале должны привести к единому знаменателю технические решения по всем ДТС.

Вместо P.S. Будущее рынка УЦ и ДТС


И напоследок хотелось бы написать про возможное схлопывание рынка УЦ.

Этим же законом изменен срок аккредитации УЦ с 5 до 3 лет. Аналогичный срок 3 года определен для аккредитации ДТС. При этом значительно возросли требования к УЦ. Теперь необходимо:

  • минимум 1 млрд рублей собственных средств (капитала) или 500 млн рублей капитала, но при этом один либо несколько филиалов или представительств УЦ должно быть размещено не менее чем в 3/4 субъектов России (аналогичное требование к ДТС);
  • финансовое обеспечение ответственности за убытки, причиненные третьим лицам в размере не менее 100 млн рублей для УЦ (сейчас это 30 млн рублей). Для ДТС размер еще не определен.

По оценкам экспертов, увеличение требований к минимальному капиталу приведет к сокращению количества УЦ более чем в 10 раз уже в 2021 (примерно с 450 до 20-40). По аналогии не ожидается и появления значительного количества ДТС, которые, скорее всего, будут созданы при ключевых УЦ (Центробанке, налоговой службе, казначействе), чтобы обслуживать их внутренние потребности. Возможно, они появятся и при нескольких крупных выживших коммерческих аккредитованных УЦ.

Пользователям или разработчикам небольших прикладных систем (тех, кто хотел бы внедрить документооборот с облачной ЭП), конечно же, интереснее работать с независимыми от удостоверяющих центров ДТС, а также взаимодействовать со всеми или большинством крупных УЦ.

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

Пишите, если есть вопросы не для комментариев вот моя почта: SGontzov@croc.ru.
Подробнее..

Поддержка токенов PKCS11 с ГОСТ-криптографией в Python. Часть I

20.02.2021 18:04:03 | Автор: admin
imageПоддержка криптографических токенов PKCS#11 с российской криптографией в скриптовых языках (Python, Tcl) давно находится в моём поле зрения. Это, прежде всего, пакет TclPKCS11 и реализованная на его базе кроссплатформенная утилита cryptoarmpkcs. Утилита cryptoarmpkcs написана на tcl/tk и функционирует на различных платформах, включая Android. Пакет TclPKCS11 версии 1.0.0 заточен на работу именно с токенами, поддерживающими ГОСТ Р 34.11-2012 и ГОСТ Р 34.10-2012. Он позволяет генерировать ключевые пары по ГОСТ Р 34.10-2012 с длиной закрытого ключа 256 и 512 бит, формировать и проверять электронную подпись. Все это можно наглядно видеть в утилите cryptoarmpkcs, в которой в качестве криптодвижка используется именно этот пакет:

image

Первым желанием было портировать этот модуль в среду Python. Но прежде чем это сделать, я посмотрел, что уже есть для работы с криптографическим токенами PKCS#11 в Python.
Вне конкуренции, на мой взгляд, здесь проект PyKCS11. Изучив его внимательно, я понял, что не составит труда добавить в него поддержку новой российской криптографии: ГОСТ Р 34.10-2012 (электронная подпись), ГОСТ Р 34.11-2012 (хэширование), ГОСТ Р 34.12-2015 и ГОСТ Р 34.13-2015 (алгоритмы шифрования Кузнечик и Магма). Я написал письмо авторам с предложением добавить российские алгоритмы, предлагая свою помощь. К сожалению, ответ меня несколько обескуражил:



И тогда я решил вернуться к этой теме немного позже, а сейчас всё внимание сосредоточил на портировании проект TckPKCS11-1.0.1 в Python. Почему всё же проект TclPKCS11? Да всё очень просто. Основная задача, которую необходимо решить на Python, связана с электронной подписью по ГОСТ Р 34.10-2012 и использование шифрования на данном этапе не предполагается. В этом контексте проект TclPKCS11 абсолютно подходит. В нём реализована поддержка следующих криптографических функций:
генерация ключевых пар по ГОСТ Р 34.10-2012 (512 и 1024 бита для открытого ключа), и даже по ГОСТ Р 34.10-2001;
подсчет хэша по ГОСТ Р 34.10-2012 (256 и 512 бит), а также по ГОСТ Р 34.11-94 и SHA1;
подписание и проверка подписи.
Из общих функций реализованы:
управление токенами (инициализация токена, установка и смена PIN-кодов);
получения списка слотов и информации о них;
импорт сертификатов и ключей (только для ГОСТ-криптографии):
установка меток для объектов (сертификаты, ключи);
и другие.
Самое главное то, что использование этих механизмов намного проще, чем использование стандартного интерфейса PKCS#11, а следовательно и проще использования пакета PyKCS11. Всё это будет видно на примерах.

I. Портирование кода модуля tclpkcs11 в модуль pyp11 для Python


Портирование заключается в адаптации кода модуля tclpkcs11 к требованиям со стороны Python. Все изменения в проекте будут касаться только модуля tclpkcs11.c. Поэтому, первое, что мы сделаем, скопируем модуль tclpkcs11.c в файл pythonpkcs11.c и в дальнейшем будем работать именно с ним. Модуль для Python назовем pyp11. Использовать для его создания будем C API Python. Почему-то этот способ многие (но не я) считают самым трудным, но зато он самый эффективный. Анализ C API для Tcl и C API для Python показал их значительное сходство, что и позволило очень быстро провести портирование. Отметим основные этапы портирования, которые вполне возможно кому-то помогут перенести те или иные модули (библиотеки) из Tcl в Python или наоборот.
Первое, в файле pythonpkcs11.c заменяем все объявления Tcl_Obj на PyObject, что вполне естественно: Tcl работает со своими объектами, а Python со своими.
Второе касается передачи параметров.
В общем виде объявление функции, реализующей ту или иную команду Tcl, в С-коде выглядит следующим образом (применительно к нашему коду):
name_proc_tcl (CliendData cd, Tcl_Interp *interp, int objc, Tcl_Obj[] *objv[] ){          . . .};

В Python аналогичный заголовок функции будет выглядеть так:
name_proc_py (PyObject *self, PyObject *args){          . . .};

В C-коде для tcl проверка количества входных параметров проводится с использованием переменной objc.
name_proc_tcl (CliendData cd, Tcl_Interp *interp, int objc, Tcl_Obj[] *objv[] ){  if (objc != 4) {          . . .    Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"pki::pkcs11::login handle slot password\"", -1));    return(TCL_ERROR);  }          . . .};

В Python параметры передаются в виде кортежа. Поэтому число переданных параметров вычисляется функцией PyTuple_Size(args):
name_proc_py (PyObject *self, PyObject *args){//Вводим переменную для числа параметров  int objc;  objc = PyTuple_Size(args);          . . .  if (objc != 3) {        PyErr_SetString(PyExc_TypeError, "pyp11_login args error (count args != 3)");return NULL;  }          . . .};

Отметим, что число параметров в коде для Tcl на единицу больше, т.к. в objv[0] хранится имя функции (аналогично функции main в C).
В приведенном коде наглядно видно как обрабатываются ошибки в Tcl и Python.
Вызов прерывания в случае ошибки для Tcl выполняется оператором
return (TCL_ERROR);
Текстовое сообщение об ошибке формируется оператором TclSetObjResult.
Для Python будут использоваться операторы return NULL и PyErr_SetString.
Теперь самое главное разбор параметров.
В Tcl каждый параметр передается как отдельный Tcl-объект, а в Python как кортеж параметров в виде Python-объектов. Поэтому, если мы хотим вносить минимальные изменения в код, целесообразно сначала распаковать кортеж по отдельным объектам, например (применительно к функции pyp11_login):
char *tcl_handle;long slotid_long;char *password;//Массив PyObject-ов для входных параметровPyObject *argspy[3];//Растаскиваем входные параметры/объекты   ("OOO" - три объекта) по своим ячейкам PyArg_ParseTuple(args, "OOO", &argspy[0], &argspy[1], &argspy[2])

Полученные объекты распаковываем с их функциональным назначением:
//Получаем строку (s) с handle библиотеки PKCS11PyArg_Parse(argspy[0], "s", &tcl_handle);//Получаем номер слота (l), в котором находится токенPyArg_Parse(argspy[1], "l", &slotid_long);//Получаем строку (s) с PIN-кодом владельца PyArg_Parse(argspy[2], "s", &password);...

Сразу оговоримся, что в C API Python имеется функция, которая позволяет сразу разбирать кортеж параметров. В этом случае можно обойтись одним оператором:
PyArg_ParseTuple(args, sls, &tcl_handle, &slotid_long, &password);

Как ни парадоксально, это практически все рекомендации.
Осталось последнее, возвращаемые значения.
Результаты выполнения команд возвращаются либо в виде строки, либо в виде списка, либо в виде словаря.
Приведём некоторые соответствия. Так для создания списка в коде для Tcl используется функция Tcl_NewObj(), а в коде для Python используется функция PyListNew(0).
Для добавления элемента в список для Tcl используется функция TclListObjAppendElement, а для Python функция PyList_Append. Все эти соответствия можно найти, сравнив код TclPKCS11 и код pyp11 (ССЛКА).
Также вместо используемых функций ckalloc и ckfree в tclpkcs11.c для Tcl, в модуле pythonpkcs11.c используются стандартные функции работы с памятью malloc и free.
После проведенного анализа модификация кода вместе с тестированием заняла пару рабочих дней.

II. Сборка и установка модуля pyp11


Итак, скачиваем архив и распаковываем его. Заходим в папку PythonPKCS11 и выполняем команду установки:
#python3 setup.py install

Лично я тестировал на платформах Windows, Linux, OS X. Отметим, что пакет TclPKCS11 успешно работает и на платформе Android.
После установки модуля переходим в папку tests и начинаем тестирование.
Pаботоспособность модуля pyp11 можно проверить даже без токена. В составе модуля есть функция pyp11.dgst, которая не привязана к токенам и позволяет посчитать хэш по ГОСТ Р 34.10-2012:
bash-4.4$ python3Python 3.7.9 (default, Feb  1 2021, 16:55:33) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import pyp11#Считаем хэш по ГОСТ Р 34.11-2012-256 (stribog256)>>> hash256 = pyp11.dgst("stribog256", "Текст для хэширования")#Считаем хэш по ГОСТ Р 34.11-2012-512 (stribog512)>>> hash512 = pyp11.dgst("stribog512", "Текст для хэширования")>>> print("STRIBOG256=" + hash256)STRIBOG256=26b8865c37831aa254706e6c3514fb23f386358e9dd858703a24d4825d2c4794>>> print("STRIBOG512=" + hash512)STRIBOG512=e92ff2063c586ec6e9c9569dad7dd503de1c88faafc8b1bf43909bfa36db92ccbf3823f0b8f5d877f10933ed7e670081018dac0929d17729422f05ce1f4c4f25>>> quit()bash-4.4$

Значение хэш возвращается в шестнадцатеричном виде.
Для перевода хэш-а в бинарный вид можно воспользоваться следующей функцией:
>>> hash256_bin = bytes(bytearray.fromhex(hash256))

Напомним, как перевести бинарный код в шестнадцатеричный:
>>> hash256 = bytes(hash256_bin).hex()>>> print("STRIBOG256_NEW=" + hash256)STRIBOG256_NEW=26b8865c37831aa254706e6c3514fb23f386358e9dd858703a24d4825d2c4794>>>

Есть еще одна функция, которая также может работать без токена. Это функция parsecert. На вход этой функции подается сертификат в DER-формате, упакованный в шестнадцатеричную кодировку:
bash-4.4$ python3Python 3.7.9 (default, Feb  1 2021, 16:55:33) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import pyp11>>> #Читаем серификат в DER-кодировке из файла>>> with open("cert_256.der", "rb") as f:...    cert_der = f.read()... >>> #Упаковываем сертификат der в hex>>> cert_der_hex = bytes(cert_der).hex()>>> #Распарсиваем сертификат>>> pubk = pyp11.parsecert(cert_der_hex)>>> 

Результатом выполнения команды pyp11.parsecert является словарь (ассоциированный список):
>>>print (pubk.keys())dict_keys(['pkcs11_id', 'pubkeyinfo', 'pubkey', 'subject', 'issuer', 'serial_number', 'tbsCertificate', 'signature_algo', 'signature'])>>>

В этом словаре находятся as1-структуры элементов сертификата. Все элементы закодированы в шестнадцатеричный формат. Среди элементов находится элемент pubkeyinfo со значением asn1-структуры subjectpublickeyinfo, элемент pubkey со значением публичного ключа, серийный номер сертификата, tbs-сертификат, который будет использоваться для проверки подписи сертификата, алгоритм подписи сертификата и значение самой подписи, а также элементы с информацией о владельце и издателе сертификата, полученные из сертификата и закодированные в шестнадцатеричное представление:
>>> subject = pubk['subject']>>> print ('SUBJECT=' + subject)SUBJECT=30820205310b3009060355040613025255312a3028060355042a0c21d09fd0b0d0b2d0b5d0bb20d090d0bdd0b0d182d0bed0bbd18cd0b5d0b2d0b8d1873135303306035504030c2cd09ed09ed09e20d09ad09ed09cd09fd090d09dd098d0af20d0add09ad09e2dd0a1d0a2d0a0d09ed099203937311d301b06092a864886f70d010901160e696e666f4072746564632e6f72673118301606052a85036401120d313137373734363733343433393116301406052a85036403120b3133383632313537373734311a301806082a85030381030101120c3030393732393131303536393130302e060355040c0c27d093d0b5d0bdd0b5d180d0b0d0bbd18cd0bdd18bd0b920d0b4d0b8d180d0b5d0bad182d0bed180310a3008060355040b0c013031353033060355040a0c2cd09ed09ed09e20d09ad09ed09cd09fd090d09dd098d0af20d0add09ad09e2dd0a1d0a2d0a0d09ed099203937315f305d06035504090c5631313931333620d0b32e20d09cd0bed181d0bad0b2d0b020d0bfd1802dd0b420312dd0b920d0a1d0b5d182d183d0bdd18cd181d0bad0b8d0b920d0b42e203130d09020d181d182d1802e203120d0bfd0bed0bc2e20323115301306035504070c0cd09cd0bed181d0bad0b2d0b0311c301a06035504080c13373720d0b32e20d09cd0bed181d0bad0b2d0b0311b301906035504040c12d0a5d0b0d180d0b8d182d0bed0bdd0bed0b2>>>

Элемент pkcs11_id берётся не из сертификата, а рассчитывается как значение хэш по SHA-1 от значения публичного ключа. При использовании функции pyp11.parsecert в данном контексте (без подключенного токена) pkcs11_id будет равен -1:
>>> pkcs11_id = pubk['pkcs11_id']>>> print ('PKCS11_ID=' + pkcs11_id)PKCS11_ID=-1>>>

Кто-то может сказать, а что, разве в Python нет средств разбора сертификатов? А как же, например, asn1crypto? Ответ заключается в том, что в этих средствах не учтены особенности российской криптографии. И вот, чтобы получить максимальную самодостаточность пакета pyp11, в него помимо функций, связанных с генерацией ключевой пары, формирования и проверки подписи, включены дополнительные функции. Например, asn1-структура pubkeyinfo необходима при проверке электронной подписи. И именно поэтому и была включена функция parsecert для частичного разбора сертификата x509.v3 и получения, в частности, asn1-структуры subjectpublickeyinfo (pubkeyinfo).
В папке tests проекта в файлах test0_* находятся соответствующие тесты.
############УБРАТЬ про FSB795 ################################
Отметим также, что для разбора сертификатов с российской криптографией можно воспользоваться пакетом fsb795:
>>> import fsb795>>> #Парсим наш сертификат с помощью fsb795>>> mycert = fsb795.Certificate(cert_der)>>> #читаем данные о владельце сертификата и типе владельце>>> dn, type = mycert.subjectCert()>>> #DN - это словарь/ассоциированный список>>> for key in dn.keys():...     print (key + '=' + dn[key])... Country=RUGN=Имя ОтчествоCN=ООО КОМПАНИЯ E=info@ooo.orgOGRN=xxxxxxxxxxxxSNILS=xxxxxxxxxxxINN=xxxxxxxxxxxxtitle=Генеральный директорOU=0O=ООО КОМПАНИЯ street=119136 г. Москва L=МоскваST=77 г. МоскваSN=Харитонов>>> 

Теперь можно переходить к работе с токенами.

III. Управление токенами PKCS#11


Для тестирования функций управления подойдет любой токен PKCS#11, даже токен без поддержки какой-либо криптографии, например RuTokenLite. Но поскольку мы ведём речь о российской криптографии, то целесообразно сразу иметь токен с поддержкой российской криптографии. Здесь мы имеем в виду ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012. Это может быть как аппаратный токен, например RuTokenECP-2.0, так и программные или облачные токены.
Установить программный токен или получить доступ к облачному токену можно, воспользовавшись утилитой cryptoarmpkcs.
Скачать утилиту cryptoarmpkcs можно здесь.
После запуска утилиты необходимо зайти на вкладку Создать токены:



На вкладке можно найти инструкции для получения токенов.
Итак, у нас токен и библиотека для работы с ним. После загрузки модуля pyp11 требуется загрузить библиотеку для работы с нашим токеном. В примерах будут использоваться библиотека librtpkcs11ecp-2.0 для работы с аппаратным токеном, библиотека libls11sw2016 для работы с программным токеном и библиотека libls11cloud.so для работы с облачным токеном. Читатели могут использовать любые токены, даже те, на которых нет российской криптографии, на них тоже можно проверить функции управления.
Итак, загружаем библиотеку командой loadmodule:
bash-4.4$ python3  Python 3.7.9 (default, Feb  1 2021, 16:55:33) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import sys>>> import pyp11>>> #Выбираем библиотеку pkcs11>>> lib = "/usr/local/lib64/librtpkcs11ecp_2.0.so">>> #Обработка ошибки при загрузке библиотеки PKCS#11>>> try:... #Вызываем команду загрузки библиотеки и плохим числом параметров...     handlelib = pyp11.loadmodule(lib, 2)... except:...     print ('Ошибка загрузки библиотеки: ')...     e = sys.exc_info()[1]...     e1 = e.args[0]...     print (e1)... Ошибка загрузки библиотеки: pyp11_load_module args error (count args != 1)>>> #Загружаем с правильным синтаксисом>>> idlib = pyp11.loadmodule(lib)>>> #Печатаем дескриптор библиотеки>>> print (idlib)pkcs0>>> 

Дескриптор загруженной библиотеки используется при её выгрузке:
>>> pyp11.unloadmodule(idlib) 

Теперь, когда библиотека загружена, можно получить список поддерживаемых её слотов и узнать есть ли в каких слотах токены. Для получения списка слотов с полной информацией о них и содержащихся в них токенах используется команда:
>>> slots = pyp11.listslots(idlib)>>>

Команда pyp11.listslots возвращает список, каждый элемент которого содержит информацию о слоте:
[<info slot1>, <info slot2>, ... , <info slotN>]
.
В свою очередь, каждый элемент этого списка также является списком, состоящим из четырех элементов:
[<номер слота>, <метка токена, находящегося в слоте>, <флаги слота и токена>, <информация о токене>]

Если слот не содержит токен, то элементы <метка токена ...> и <информация о слоте> содержат пустое значение.
Наличие токена в слоте определяется по наличию флага TOKEN_PRESENT в списке <флаги слота и токена>:
bash-4.4$ python3Python 3.7.9 (default, Feb  1 2021, 16:55:33) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import sys>>> import pyp11>>> #Выбираем библиотеку>>> #lib = '/usr/local/lib64/libls11sw2016.so'>>> lib = '/usr/local/lib64/librtpkcs11ecp_2.0.so'>>> #Загружаем библиотеку>>> libid = pyp11.loadmodule(lib)>>> #Дескриптор библиотеки>>> print (libid)pkcs0>>> #Загружаем список слотов>>> slots = pyp11.listslots(libid)>>> tokpr = 0>>> #Ищем первый подключенный токен>>> while (tokpr == 0):... #Перебираем слоты...     for v in slots:...         #Список флагов текущего слота...         flags = v[2]... #Проверяем наличие в стоке токена...         if (flags.count('TOKEN_PRESENT') !=0):...             tokpr = 1... #Избавляемся от лишних пробелов у метки слота...             lab = v[1].strip()...             infotok = v[3]...             slotid = v[0]...             break...     if (tokpr == 0):...         input ('Нет ни одного подключенного токена.\nВставьте токен и нажмите ВВОД')...     slots = pyp11.listslots(libid)... #Информация о подключенном токене... Нет ни одного подключенного токена.Вставьте токен и нажмите ВВОД''>>> #Информация о подключенном токене>>> print ('LAB="' + lab + '", SLOTID=' + str(slotid))LAB="Rutoken lite <no label>", SLOTID=0>>> print ('FLAGS:', flags)FLAGS: ['TOKEN_PRESENT', 'RNG', 'LOGIN_REQUIRED', 'SO_PIN_TO_BE_CHANGED', 'REMOVABLE_DEVICE', 'HW_SLOT']>>>

Если взглянуть на флаги (FLAGS:) подключенного токена, то в них отсутствует флаг 'TOKEN_INITIALIZED'. Отсутствие этого флага говорит о том, что токен не инициализирован и требуется его инициализация:
#Проверяем, что токен проинициализирован>>> if (flags.count('TOKEN_INITIALIZED') == 0''):...         #Инициализируем токен...         dd = pyp11.inittoken (libid, 0, '87654321',"TESTPY2")...         >>>

Как видим, для инициализации токена используется следующая команда:
pyp11.inittoken (<дискриптор библиоткети>, <номер слота>, <SO-PIN>, <метка токена>)

Естественно, токен можно переинициализировать независимо от наличия флага 'TOKEN_INITIALIZED', только надо иметь в виду, что переинициализация токена ведет к уничтожению на нем всех объектов (ключи, сертификаты и т.д).
После инициализации токена должен быть проинициализирован USER-PIN. Эту операцию, как правило, делает производитель или продавец токена:
pyp11.inituserpin (<дискриптор библиоткети>, <номер слота>, <SO-PIN>, <USER-PIN>)

При этом выставляется флаг 'USER_PIN_TO_BE_CHANGED', который напоминает владельцу токена, что надо бы сменить свой USER-PIN (параметр 'user'):
pyp11.setpin (<дискриптор библиоткети>, <номер слота>, <'user'|'so'>,<текущий PIN-код>, <новый PIN-код>)

Сегодня модно получать в УЦ токены с закрытыми ключами и предустановленными PIN-кодами и ключевой парой. И, как правило, получателей не предупреждают, что целесообразно PIN-коды поменять, и не говорят, как это сделать. Я бы рекомендовал использовать для этого уже упоминавшуюся утилиту cryptoarmpkcs:

image

В папке tests проекта pyp11 лежат три теста test1_0_inittoken.py, test1_1_inituserpin.py и test1_2_change_userpin, которые наглядно демонстрируют инициализацию токена. Выполнять их надо в порядке перечисления.
Было бы несправедливо не показать инициализацию токена с использованием уже упоминавшегося пакета PyKCS11:
$ python3Python 3.7.9 (default, Feb  1 2021, 16:55:33) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import PyKCS11>>> #Библиотека PKCS#11>>> lib = '/usr/local/lib64/librtpkcs11ecp_2.0.so'>>> pkcs11.load(lib)>>> #Получаем список слотов с токенами>>> slots = pkcs11.getSlotList(tokenPresent=True)>>> #Ищем первый подключенный токен>>> while (len(slots) == 0):...     input ('Нет ни одного подключенного токена.\nВставьте токен и нажмите ВВОД')...     #Получаем список слотов с токенами...     slots = pkcs11.getSlotList(tokenPresent=True)... Нет ни одного подключенного токена.Вставьте токен и нажмите ВВОД''>>>>>> #Берём первый подключенный токен>>> slot = slots[0]>>> #Закрываем все сессии на токене >>> #SO-PIN>>> so_pin = '87654321'>>> lab_tok = "myLabel">>> #Инициализация токена>>> pkcs11.initToken(slot, so_pin, lab_tok)>>> session = pkcs11.openSession(slot, PyKCS11.CKF_SERIAL_SESSION | PyKCS11.CKF_RW_SESSION)>>> #Установка первичного USER-PIN >>> init_pin = '1234'>>> session.login(so_pin, user_type=PyKCS11.CKU_SO)>>> session.initPin(init_pin)>>> session.logout()>>> #Новый USER-PIN>>> user_pin = '01234567'>>> session.login(init_pin)>>> # change PIN>>> session.setPin(init_pin, user_pin)>>> session.logout()>>> quit()$ 

IV. Ключевая пара, электронная подпись и её проверка


Итак, наш токен готов в работе: мы его проинициализировали и установили метку, но самое главное, мы поменяли PIN-коды (USER, SO).
Первым делом необходимо убедиться, что наш токен поддерживает необходимые нам криптографические механизмы. Поскольку речь идет о ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012, то токен должен поддерживать механизмы CKM_GOST* в соответствии рекомендациями ТК-26.
Для получения списка механизмов используется команда pyp11.lictmechs:
<список механизмов> = pyp11.listmech(<идентификатор библиотеки>, <номер слота>)

Как ни странно, но токены могут не иметь поддержки криптомеханизмов, например, RuToken Lite. Они нас интересовать не будут. Мы будем использовать только токены с поддержкой ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012:
$ python3Python 3.7.9 (default, Feb  1 2021, 16:55:33) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import pyp11>>> #Выбираем библиотеку>>> #Программный токен>>> lib = '/usr/local/lib64/libls11sw2016.so'>>> #Для Windows>>> #lib='C:\Temp\ls11sw2016.dll'>>> #Облачный токен>>> #lib = '/usr/local/lib64/libls11cloud.so'>>> #Аппаратный токен>>> #lib = '/usr/local/lib64/librtpkcs11ecp_2.0.so'>>> #Закгружаем выбранную библиотеку>>> aa = pyp11.loadmodule(lib)>>> listmech = pyp11.listmechs(aa, 0)>>> print ('\tКриптографические механизмы токена')        Криптографические механизмы токена>>> for mech in listmech:...     print(mech)... 
Криптографические механизмы
CKM_GOSTR3410_KEY_PAIR_GEN (0x1200)CKM_GOSTR3410_512_KEY_PAIR_GEN (0xD4321005)CKM_GOSTR3410 (0x1201)CKM_GOSTR3410_512 (0xD4321006)CKM_GOSTR3410_WITH_GOSTR3411 (0x1202)CKM_GOSTR3410_WITH_GOSTR3411_12_256 (0xD4321008)CKM_GOSTR3410_WITH_GOSTR3411_12_512 (0xD4321009)CKM_GOSTR3410_DERIVE (0x1204)CKM_GOSTR3410_12_DERIVE (0xD4321007)CKM_GOSR3410_2012_VKO_256 (0xD4321045)CKM_GOSR3410_2012_VKO_512 (0xD4321046)CKM_KDF_4357 (0xD4321025)CKM_KDF_GOSTR3411_2012_256 (0xD4321026)CKM_KDF_TREE_GOSTR3411_2012_256 (0xD4321044)CKM_GOSTR3410_KEY_WRAP (0x1203)CKM_GOSTR3410_PUBLIC_KEY_DERIVE (0xD432100A)CKM_LISSI_GOSTR3410_PUBLIC_KEY_DERIVE (0xD4321037)CKM_GOST_GENERIC_SECRET_KEY_GEN (0xD4321049)CKM_GOST_CIPHER_KEY_GEN (0xD4321048)CKM_GOST_CIPHER_ECB (0xD4321050)CKM_GOST_CIPHER_CBC (0xD4321051)CKM_GOST_CIPHER_CTR (0xD4321052)CKM_GOST_CIPHER_OFB (0xD4321053)CKM_GOST_CIPHER_CFB (0xD4321054)CKM_GOST_CIPHER_OMAC (0xD4321055)CKM_GOST_CIPHER_KEY_WRAP (0xD4321059)CKM_GOST_CIPHER_ACPKM_CTR (0xD4321057)CKM_GOST_CIPHER_ACPKM_OMAC (0xD4321058)CKM_GOST28147_KEY_GEN (0x1220)CKM_GOST28147 (0x1222)CKM_GOST28147_KEY_WRAP (0x1224)CKM_GOST28147_PKCS8_KEY_WRAP (0xD4321036)CKM_GOST_CIPHER_PKCS8_KEY_WRAP (0xD432105A)CKM_GOST28147_ECB (0x1221)CKM_GOST28147_CNT (0xD4321825)CKM_GOST28147_MAC (0x1223)CKM_KUZNYECHIK_KEY_GEN (0xD4321019)CKM_KUZNYECHIK_ECB (0xD432101A)CKM_KUZNYECHIK_CBC (0xD432101E)CKM_KUZNYECHIK_CTR (0xD432101B)CKM_KUZNYECHIK_OFB (0xD432101D)CKM_KUZNYECHIK_CFB (0xD432101C)CKM_KUZNYECHIK_OMAC (0xD432101F)CKM_KUZNYECHIK_KEY_WRAP (0xD4321028)CKM_KUZNYECHIK_ACPKM_CTR (0xD4321042)CKM_KUZNYECHIK_ACPKM_OMAC (0xD4321043)CKM_MAGMA_KEY_GEN (0xD432102A)CKM_MAGMA_ECB (0xD4321018)CKM_MAGMA_CBC (0xD4321023)CKM_MAGMA_CTR (0xD4321020)CKM_MAGMA_OFB (0xD4321022)CKM_MAGMA_CFB (0xD4321021)CKM_MAGMA_OMAC (0xD4321024)CKM_MAGMA_KEY_WRAP (0xD4321029)CKM_MAGMA_ACPKM_CTR (0xD4321040)CKM_MAGMA_ACPKM_OMAC (0xD4321041)CKM_GOSTR3411 (0x1210)CKM_GOSTR3411_12_256 (0xD4321012)CKM_GOSTR3411_12_512 (0xD4321013)CKM_GOSTR3411_HMAC (0x1211)CKM_GOSTR3411_12_256_HMAC (0xD4321014)CKM_GOSTR3411_12_512_HMAC (0xD4321015)CKM_PKCS5_PBKD2 (0x3B0)CKM_PBA_GOSTR3411_WITH_GOSTR3411_HMAC (0xD4321035)CKM_TLS_GOST_KEY_AND_MAC_DERIVE (0xD4321033)CKM_TLS_GOST_PRE_MASTER_KEY_GEN (0xD4321031)CKM_TLS_GOST_MASTER_KEY_DERIVE (0xD4321032)CKM_TLS_GOST_PRF (0xD4321030)CKM_TLS_GOST_PRF_2012_256 (0xD4321016)CKM_TLS_GOST_PRF_2012_512 (0xD4321017)CKM_TLS12_MASTER_KEY_DERIVE (0x3E0)CKM_TLS12_KEY_AND_MAC_DERIVE (0x3E1)CKM_TLS_MAC (0x3E4)CKM_TLS_KDF (0x3E5)CKM_TLS_TREE_GOSTR3411_2012_256 (0xD4321047)CKM_EXTRACT_KEY_FROM_KEY (0x365)CKM_SHA_1 (0x220)CKM_MD5 (0x210)

>>> quit()$

Теперь, когда мы убедились, что токен поддерживает российскую криптографию, можно приступить к созданию ключевой пары на токене и использовать ее закрытый ключ для подписания различных документов.
Напомним, что закрытый и открытый ключи это не только их значения (для открытого ключа ГОСТ Р 34.10-2012-256 это 512 бит, а для открытого ключа ГОСТ Р 34.10-2012-512 это 1024 бита), но и параметры схемы цифровой подписи (п. 5.2 ГОСТ Р 34.10-2012). В дальнейшем параметры схемы цифровой подписи для простоты будем называть параметрами (криптопараметрами) ключевой пары.
Криптопараметры при генерации ключевой пары задаются OID-ами. В настоящее время TK-26 определил следующие oid-ы для криптопараметров алгоритма подписи ГОСТ Р 34.10-2012 с ключом 256:
  • 1.2.643.7.1.2.1.1.1 (id-tc26-gost-3410-12-256-paramSetA);
  • 1.2.643.7.1.2.1.1.2 (id-tc26-gost-3410-12-256-paramSetB;
  • 1.2.643.7.1.2.1.1.3 (id-tc26-gost-3410-12-256-paramSetC);
  • 1.2.643.7.1.2.1.1.4 (id-tc26-gost-3410-12-256-paramSetD).

При этом продолжают действовать так называемые OID-ы параметров от КриптоПро:
  • 1.2.643.2.2.35.1 (id-GostR3410-2001-CryptoPro-A-ParamSet);
  • 1.2.643.2.2.35.2 (d-GostR3410-2001-CryptoPro-B-ParamSet);
  • 1.2.643.2.2.35.3 (id-GostR3410-2001-CryptoPro-C-ParamSet);
  • 1.2.643.2.2.36.0 (id-GostR3410-2001-CryptoPro-XchA-Param)Set;
  • 1.2.643.2.2.36.1 (id-GostR3410-2001-CryptoPro-XchB-Param)Set.

Кто-то может сказать, а что это за каша такая? Но если смотреть по сути, то окажется, что параметры КриптоПро с OID-ами 1.2.643.2.2.35.1, 1.2.643.2.2.35.2, 1.2.643.2.2.35.3 соответствуют параметрам ТК-26 с OID-ами 1.2.643.7.1.2.1.1.1, 1.2.643.7.1.2.1.1.2, 1.2.643.7.1.2.1.1.3 соответственно. Далее ещё интереснее. Параметр КриптоПро id-GostR3410-2001-CryptoPro-XchA-Param соответствует параметру id-GostR3410-2001-CryptoPro-A-ParamSet, а параметр id-GostR3410-2001-CryptoPro-XchB-Param параметру id-GostR3410-2001-CryptoPro-C-ParamSet того же КриптоПро. Если не запутались, то идём дальше.
С криптопараметрам для алгоритма подписи ГОСТ Р 34.10-2012 с ключом 512 проще:
  • 1.2.643.7.1.2.1.2.1 (id-tc26-gost-3410-2012-512-paramSetA);
  • 1.2.643.7.1.2.1.2.2 (id-tc26-gost-3410-2012-512-paramSetB);
  • 1.2.643.7.1.2.1.2.3 (id-tc26-gost-3410-2012-512-paramSetC);

Для генерации ключевой пары используется следующая команда:
<идентификатор словаря> = pyp11.keypair(<идентификатор библиотеки>, <номер слота с токеном>, <тип ключевой пары>, <OID криптопараметра>, <метка/CKA_LABEL>)

Единственное, с чем мы не сталкивались, это <тип ключевой пары>:
<тип ключевой пары> := 'g12_256' | 'g12_512'
Таким образом, если мы хотим получить пару по алгоритму подписи ГОСТ Р 34.10-2012 с ключом 512, то задаем тип 'g12_512', например:
genkey = pyp11.keypair(libid, slotid, 'g12_512', '1.2.643.7.1.2.1.2.2', 'KeyGost512')

Для алгоритма подписи ГОСТ Р 34.10-2012 с ключом 256 генерация может выглядеть так:
genkey256 = pyp11.keypair(libid, slotid, 'g12_256', '1.2.643.7.1.2.1.1.3', 'KeyGost256')

Перед генерацией ключевой пары необходимо обязательно залогиниться на токене:
pyp11.login(<идентификатор библиотеки>, <номер слота>, 'USER-PIN')

После выполнения требуемой операции целесообразно выполнить logout:
pyp11.logout(<идентификатор библиотеки>, <номер слота>)

При успешной генерации ключевой пары возвращается ассоциированный список (словарь), например:
>>> pyp11.login(libid, slotid, '01234567')
1
>>> genkey256 = pyp11.keypair(libid, slotid, 'g12_256', '1.2.643.7.1.2.1.1.3', 'KeyGost256')
>>> print (genkey256.keys())
dict_keys(['pkcs11_handle', 'pkcs11_slotid', 'hobj_pubkey', 'hobj_privkey', 'pkcs11_id', 'pkcs11_label', 'pubkey', 'pubkey_algo', 'pubkeyinfo', 'type'])
>>> pyp11.logout(libid, slotid)
1
>>>
Среди возвращаемых значений находятся указатели на открытый ('hobj_pubkey') и закрытый ключи ('hobj_privkey'). Последний мы будем использовать при подписании. Среди возвращаемых значений находится и CKA_ID открытого и закрытого ключей ('pkcs11_id'). Элемент pkcs11_id также может использоваться при подписании для поиска закрытого ключа. Напомним, CKA_ID это значение хэша SHA-1 от значения открытого ключа, которое находится в элементе 'pubkey'. При генерации ключевой пары CKA_ID автоматически выставляется для закрытого и открытого ключей. Именно по ним, как правило, ищут соответствие между ключами. Можно распечатать все возвращаемые значения:
>>> for key in genkey256.keys():...     print (key + '= ' + str(genkey256.get(key)))... pkcs11_handle= pkcs0pkcs11_slotid= 0hobj_pubkey= hobj0100000000000000hobj_privkey= hobj0200000000000000pkcs11_id= dd22fe35aeb7eb2ebcad7199b117eb3a7b5f5813pkcs11_label= KeyGost256pubkey= 4c2ed60bc5771b2a6616af58c8dd202b9463dde9bd1de028335e718634761e360a25b2f337c2e67c28402cd49fff4f708130a80dc479301b21ceb9324c47464bpubkey_algo= 1 2 643 7 1 1 1 1pubkeyinfo= 302106082a85030701010101301506092a850307010201010306082a8503070101020203430004404c2ed60bc5771b2a6616af58c8dd202b9463dde9bd1de028335e718634761e360a25b2f337c2e67c28402cd49fff4f708130a80dc479301b21ceb9324c47464btype= pkcs11>>> 

Для формирования электронной подписи и её проверки сохраним следующие значения:
>>> hprivkey = genkey256.get("hobj_privkey")>>> pkcs11_id = genkey256.get("pkcs11_id")>>> pubkeyinfo = genkey256.get("pubkeyinfo")>>> 

Электронная подпись (ЭП) документа представляет собой подписанный хэш от этого документа.
Поэтому сначала считается соответствующий хэш:
<переменная для хранения хэш > = pyp11.digest(<идентификатор библиотеки>, <слот токена>, 'stribog256' | 'stribog512', <документ>)
Значение хэш всегда возвращается в шестнадцатеричном виде.
Итак, если мы хотим получить подпись по алгоритму ГОСТ Р 34.10-2012 с ключом 256 бит, то нам сначала надо посчитать хэш по алгоритму хэширования ГОСТ Р 34.11-2012 с длиной 256 бит, а затем подписать полученный хэш с использованием механизма 'CKM_GOSTR3410':
<переменная для  ЭП> = pyp11.sign(<идентификатор библиотеки>, <слот токена>, 'CKM_GOSTR3410' | 'CKM_GOSTR3410_512', <хэш документа>, <hobj_privkey|pkcs11_id>)

Хэш документа должен быть в шестнадцатеричном виде. Электронная подпись также возвращается в шестнадцатеричном виде.
Ниже приведем пример кода формирования ЭП:
bash-4.4$ python3Python 3.7.9 (default, Feb  1 2021, 16:55:33) [GCC 8.4.0] on linuxType "help", "copyright", "credits" or "license" for more information.>>> import pyp11>>> lib = '/usr/local/lib64/libls11sw2016.so'>>> libid = pyp11.loadmodule(lib)>>> slotid = 0>>> #Незабывайте лигиниться на токене!!!>>> pyp11.login(libid, slotid, '01234567')1>>> genkey256 = pyp11.keypair(libid, slotid, 'g12_256', '1.2.643.7.1.2.1.1.3', 'KeyGost256')>>> hprivkey = genkey256.get("hobj_privkey")>>> pkcs11_id = genkey256.get("pkcs11_id")>>> pubkeyinfo = genkey256.get("pubkeyinfo")>>> hashdoc_hex = pyp11.digest(libid, slotid, 'stribog256', 'Подписываемый документ')>>> #Для ЭП используется hobj_privkey>>> sign1 = pyp11.sign(libid, slotid, 'CKM_GOSTR3410', hashdoc_hex, hprivkey)>>> #Для ЭП используется pkcs11_id (CKA_ID)>>> sign2 = pyp11.sign(libid, slotid, 'CKM_GOSTR3410', hashdoc_hex, pkcs11_id)>>> print ('SIGN1=' + sign1 )SIGN1=5b3f881153f50d9a8da6bb37bb83f54fe997d074672c29c2c0aeb22739a14f1e776b8427e262b098c75abe3a4faffe383d3e2cc406afa09efb3e783919b4ca11>>> print ('SIGN2=' + sign2) SIGN2=441a29206a3622a9c76282b71b4fcdbf4c15034d0f0be7b1f711c6d5eef8162a2a2876a5d375cb56e23fc76173cacf88b620fd793cf756589a76cbee6b1fd27a>>> pyp11.logout(libid, slotid)1>>> 

Для проверки подписи используется asn1-структура открытого ключа subjectPublicKeyInfo, которую мы сохранили после генерации ключевой пары в переменной pubkeyinfo:
 pubkeyinfo = genkey256.get("pubkeyinfo")

Для проверки подписи используется следующая команда:
pyp11.sign(<идентификатор библиотеки>, <слот токена>, <хэш документа в hex>, <подпись документа в hex>, <asn1-subjectPublicKeyInfo>)

Команда возвращает 1 (единицу), если подпись прошла проверку, и 0 (ноль), если проверка не прошла.
Продолжим наш пример проверкой двух полученных подписей:
>>> verify1 = pyp11.verify(libid, slotid, hashdoc_hex, sign1, pubkeyinfo)>>> print (verify1)1>>> verify2 = pyp11.verify(libid, slotid, hashdoc_hex, sign2, pubkeyinfo)>>> print (verify2)1>>> 

Как видим обе полученные подписи корректны.

V. Проверка электронной подписи сертификата


Используя полученные знания, напишем пример проверки электронной подписи сертификата:
#!/usr/bin/python3#-*- coding: utf-8 -*-import pyp11print('Проверка подписи сертификата')#Библиотека для токенаlib = '/usr/local/lib64/libls11sw2016.so'aa = pyp11.loadmodule(lib)print (aa)#Файл с корневым сертификатом в DER-кодировкеfileCA = "CA_12_512.der"#Файл с сертификатом пользователя в DER-кодировкеfileUser = "habrCA_12_512.der"#Читаем корневой сертификат в DER-кодировке из файлаwith open(fileCA, "rb") as f:    certCA = f.read()#Упаковываем der в hexcertCA_hex = bytes(certCA).hex()#Читаем сертификат пользователя в DER-кодировке из файлаwith open(fileUser, "rb") as f:    certHabr = f.read()#Упаковываем der в hexcertHabr_hex = bytes(certHabr).hex()print ('Разбираем корневой сертификат')parseCA = pyp11.parsecert (aa, 0, certCA_hex)print ('Разбираем сертификат пользователя')parseHabre = pyp11.parsecert (certHabr_hex)print (parseHabre.keys())#Проверяем, что издатель сертификата совпадает с владельцем корневого сертификатаif (parseCA.get('subject') != parseHabre.get('issuer')):    print ('Сертификат выдан на другом УЦ')    quit()print ('Сертификат выдан на данном УЦ')#Переводим tbsCertificate пользователь в binarytbs_hex = parseHabre.get('tbsCertificate')tbsHabrDer = bytes(bytearray.fromhex(tbs_hex))#tbsHabrDer = '1111'#Получаем хэш для tbs-сертификатаhashTbs_hex = pyp11.digest(aa, 0, "stribog512", tbsHabrDer)#hashTbs_hex = pyp11.digest(aa, 0, "stribog256", tbsHabrDer)verify = pyp11.verify(aa, 0,  hashTbs_hex, parseHabre.get('signature'), parseCA.get('pubkeyinfo'))#verify = pyp11.verify(aa, 0,  hashTbs_hex, parseHabre.get('signature'), parseHabre.get('pubkeyinfo'))print (verify)if (verify != 1):    print ('Подпись сертификата не прошла проверку')    quit()print ('Подпись сертификата прошла проверку')quit()

VI. Работа с объектами токена


Основными объектами, с которыми приходится иметь дело, работая с токенами PKCS#11, являются сертификаты и ключи. И те и другие имеют атрибуты. Нас в первую очередь интересуют атрибуты CKA_LABEL или метка объекта и СКА_ID или идентификатор объекта. Именно атрибут CKA_ID используется для доступа и к сертификатам и ключам.
Уже имея в своем распоряжении рассмотренные выше команды модуля pyp11, можно создать ключевую пару и сформировать подписанный запрос на сертификат. Отправить полученный запрос в удостоверяющий центр и получить там сертификат. Но получив сертификат, возникает вопрос как его поставить на токен и привязать к ключевой паре? Именно эту задачу решает команда pyp11.importcert:
<переменная для CKA_ID> = pyp11.importcert(<идентификатор библиотеки>, <слот токена>, <сертификат в DER-формате и hex-кодировке>, <метка CKA_LABEL>)

Как работает команда? Первым делом она вычисляет по открытому ключу сертификата идентификатор CKA_ID. Именно этот идентификатор будет возвращен в hex-кодировке после успешного размещения сертификата на токене. После установки сертификата на токен в DER-формате, устанавливаются его атрибуты CKA_ID и CKA_LABEL.
Если вам необходимо связать тройку <сертификат> x <открытый ключ> x <закрытый ключ> не только по CKA_ID, но и по метке CKA_LABEL, то необходимо установить метку у ключевой пары аналогичную метке сертификата. Для этого используется команда rename:
pyp11.rename(<идентификатор библиотеки>, <слот токена>, <тип объекта>, <ассоциированный список>)

В <типе объекта> указывается, к каким типам объектов будет применяться команда: 'cert' | 'key' | 'all' (сертификаты, ключевая пара, к тому и другому).
Команда rename позволяет менять не только CKA_LABEL, но и CKA_ID. Конкретные объекты могут задаваться идентификаторами объектов CKA_ID (pkcs11_id), например:
#Импортируем сертификат и получаем его CKA_IDlabcert = 'LabelNEW'ckaid = pyp11.importcert(aa, 0, cert_der_hex, labcert)#Устанавливаем метку сертификата и для ключей#Готовим словарьldict = dict(pkcs11_id=ckaid, pkcs11_label=labcert)#Меняем метки у ключейpyp11.rename(aa, 0, 'key', ldict)

Аналогичным образом меняется атрибут CKA_ID. В этом случае в словарь вместо метки указывается новый CKA_ID:
ldict = dict(pkcs11_id=ckaid, pkcs11_id_new=11111)

Аналогичным образом можно удалить объекты:
pyp11.delete(<идентификатор библиотеки>, <слот токена>, <тип объекта>, <ассоциированный список>)

При уничтожении в словарь попадает только один элемент, который будет указывать на удаляемые объекты. Это либо CKA_ID (ключ pkcs11_id) либо непосредственно handle-объекта (как правило, его можно получить по команде pyp11.listobjects, ключ pkcs11_handle):
ldict = dict(pkcs11_id=ckaid)#Или с handle-объекта:#ldict = dict(hobj=pkcs11_handle)#Уничтожить личный сертификат с ключамиpyp11.login(aa. 0, '01234567')pyp11.delete(aa, 0, 'all', ldict)pyp11.logout(aa, 0)

Упомянем еще об одной очень редко используемой команде. Это команда закрытия сессий на токене:
pyp11.closesession(<идентификатор библиотеки>)

Эту команду следует вызывать, когда возникнет ошибка PKCS11_ERROR SESSION_HANDLE_INVALID, а затем повторить команду, на которой возникла ошибка. Эта ошибка может возникнуть при кратковременном извлечении токена из компьютера при работе вашей программы.
И завершим мы рассмотрение командой pyp11.listcertsder:
<список сертификатов> = pyp11.listcerts(<идентификатор библиотеки>, <слот токена>)

Вот пример кода:
#!/usr/bin/python3#-*- coding: utf-8 -*-import sysimport timeimport pyp11print('Список сертификатов токена')aa = pyp11.loadmodule('/usr/local/lib64/libls11sw2016.so')lcerts = pyp11.listcerts(aa, 0)if (len(lcerts) == 0):    print ('На токене нет сертификатов')    quit()#Перебираем сертификатыfor cert in lcerts:    #Информация о сертификате    for key in cert:        print (key + ': ' + cert[key])#Сравним с pyp11.listobjectslm = pyp11.listobjects(aa, 0, 'cert', 'value')print('Работа с listobjects:')for obj in lm:    for key in obj:        print (key + ': ' + obj[key])quit()

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

Заключение


Опыт использования аналогичного модуля tclpkcs11 показывает, что функциональности, заложенной в модуль pyp11 для Python, с лихвой хватит для его использования в ИОК для работы с электронной подписью на базе российской криптографии. Более того, во второй части статьи будет рассмотрен класс token, в рамках которого будут создаваться объекты для подключенных токенов. И это позволит ещё больше упростить работу с токенами. Кстати, аналогичный класс для tclpkcs11 уже имеется.
Но в заключении я хотел бы вернуться к началу статьи, а именно к проекту PyKCS11.
Когда я писал письмо авторам проекта PyKCS11, то я уже добавил в него поддержку российской криптографии и сообщал им об этом:



Сейчас заканчивается тестирования PyKCS11 для российской криптографии. Кстати, модуль pyp11 хорошо дополняет PyPCS11. Поэтому должна появиться и третья часть статьи, в которой будет рассказано, как добавить поддержку российской криптографии в проект PyKCS11.
Подробнее..

Поддержка токенов PKCS11 с ГОСТ-криптографией в Python. Часть II Обёртка PyKCS11

26.03.2021 18:19:00 | Автор: admin
image Подошло время рассказать как была добавлена поддержка поддержка российской криптографии в проект PyKCS11. Всё началось с того, что мне на глаза попалась переписка разработчика проекта PyKCS11 с потенциальными потребителями по поводу возможной поддержки алгоритмов ГОСТ Р 34.10-2012 в нём. В этой переписке автор PkCS11 сказал, что не собирается включать поддержку российских криптоалгоритмов до тех пор, пока они не будут стандартизованы.
Ту же самую мысль он выразил и мне, когда я предложил ему это сделать. И не просто сделать, а выслал соответствующий программный код:

image

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

I. Добавляем поддержку российских криптоалгоритмов


Итак, что же было сделано. Я фактически последовал одному из советов автора проекта PyKCS11:
What I can propose you is to create a PyKCS11_GOST.py file with the constant names and functions you want in order to extend PyKCS11 with GOST support.
(Я могу предложить вам создать файл PyKCS11_GOST.py с именами констант и функциями, которыми вы хотите расширить PyKCS11 для поддержки ГОСТ.)

Все константы, утвержденные ТК-26 для PKCS#11, были сведены в один файл pkcs11t_gost.h, помещенный в папку src:
//ТК-26#define NSSCK_VENDOR_PKCS11_RU_TEAM 0xd4321000 #define NSSCK_VENDOR_PKSC11_RU_TEAM NSSCK_VENDOR_PKCS11_RU_TEAM#define CK_VENDOR_PKCS11_RU_TEAM_TC26 NSSCK_VENDOR_PKCS11_RU_TEAM#define CKK_GOSTR3410_512 0xd4321003UL#define CKK_KUZNYECHIK 0xd4321004UL#define CKK_MAGMA 0xd4321005UL#define CKK_GOSTR3410_256 0xd4321006UL#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411_TC26_V1 0xd4321801UL#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411_2012_256 0xd4321002UL#define CKP_PKCS5_PBKD2_HMAC_GOSTR3411_2012_512 0xd4321003UL#define CKM_GOSTR3410_512_KEY_PAIR_GEN0xd4321005UL#define CKM_GOSTR3410_5120xd4321006UL#define CKM_GOSTR3410_WITH_GOSTR34110x00001202#define CKM_GOSTR3410_WITH_GOSTR3411_12_2560xd4321008UL#define CKM_GOSTR3410_WITH_GOSTR3411_12_5120xd4321009UL#define CKM_GOSTR3410_12_DERIVE0xd4321007UL#define CKM_GOSR3410_2012_VKO_2560xd4321045UL#define CKM_GOSR3410_2012_VKO_5120xd4321046UL#define CKM_KDF_43570xd4321025UL#define CKM_KDF_GOSTR3411_2012_2560xd4321026UL#define CKM_KDF_TREE_GOSTR3411_2012_2560xd4321044UL#define CKM_GOSTR3410_PUBLIC_KEY_DERIVE0xd432100AUL#define CKM_LISSI_GOSTR3410_PUBLIC_KEY_DERIVE0xd4321037UL#define CKM_GOST_GENERIC_SECRET_KEY_GEN0xd4321049UL#define CKM_GOST_CIPHER_KEY_GEN0xd4321048UL#define CKM_GOST_CIPHER_ECB0xd4321050UL#define CKM_GOST_CIPHER_CBC0xd4321051UL#define CKM_GOST_CIPHER_CTR0xd4321052UL#define CKM_GOST_CIPHER_OFB0xd4321053UL#define CKM_GOST_CIPHER_CFB0xd4321054UL#define CKM_GOST_CIPHER_OMAC0xd4321055UL#define CKM_GOST_CIPHER_KEY_WRAP0xd4321059UL#define CKM_GOST_CIPHER_ACPKM_CTR0xd4321057UL#define CKM_GOST_CIPHER_ACPKM_OMAC0xd4321058UL#define CKM_GOST28147_PKCS8_KEY_WRAP0xd4321036UL#define CKM_GOST_CIPHER_PKCS8_KEY_WRAP0xd432105AUL#define CKM_GOST28147_CNT0xd4321825UL#define CKM_KUZNYECHIK_KEY_GEN0xd4321019UL#define CKM_KUZNYECHIK_ECB0xd432101AUL#define CKM_KUZNYECHIK_CBC0xd432101EUL#define CKM_KUZNYECHIK_CTR0xd432101BUL#define CKM_KUZNYECHIK_OFB0xd432101DUL#define CKM_KUZNYECHIK_CFB0xd432101CUL#define CKM_KUZNYECHIK_OMAC0xd432101FUL#define CKM_KUZNYECHIK_KEY_WRAP0xd4321028UL#define CKM_KUZNYECHIK_ACPKM_CTR0xd4321042UL#define CKM_KUZNYECHIK_ACPKM_OMAC0xd4321043UL#define CKM_MAGMA_KEY_GEN0xd432102AUL#define CKM_MAGMA_ECB0xd4321018UL#define CKM_MAGMA_CBC0xd4321023UL#define CKM_MAGMA_CTR0xd4321020UL#define CKM_MAGMA_OFB0xd4321022UL#define CKM_MAGMA_CFB0xd4321021UL#define CKM_MAGMA_OMAC0xd4321024UL#define CKM_MAGMA_KEY_WRAP0xd4321029UL#define CKM_MAGMA_ACPKM_CTR0xd4321040UL#define CKM_MAGMA_ACPKM_OMAC0xd4321041UL#define CKM_GOSTR3411_12_2560xd4321012UL#define CKM_GOSTR3411_12_5120xd4321013UL#define CKM_GOSTR3411_12_256_HMAC0xd4321014UL#define CKM_GOSTR3411_12_512_HMAC0xd4321015UL#define CKM_PBA_GOSTR3411_WITH_GOSTR3411_HMAC0xd4321035UL#define CKM_TLS_GOST_KEY_AND_MAC_DERIVE0xd4321033UL#define CKM_TLS_GOST_PRE_MASTER_KEY_GEN0xd4321031UL#define CKM_TLS_GOST_MASTER_KEY_DERIVE0xd4321032UL#define CKM_TLS_GOST_PRF0xd4321030UL#define CKM_TLS_GOST_PRF_2012_2560xd4321016UL#define CKM_TLS_GOST_PRF_2012_5120xd4321017UL#define CKM_TLS_TREE_GOSTR3411_2012_2560xd4321047UL

В этот перечень вошли механизмы как необходимые для формирования и проверки подписи по (ГОСТ Р 34.10-2012) ГОСТ Р 34.10-2012, так и шифрования (ГОСТ Р 34.12-2015 и ГОСТ Р 34.13-2015 алгоритмы шифрования Кузнечик и Магма). Естественно, здесь же присутствуют и алгоритмы хэширования ГОСТ Р 34.11-2012.
Для того, чтобы ГОСТ-овые константы попали в процесс сборки модуля, необходимо добавить в файл pkcs11.i (файл для SWIG) оператор включения файла pkcs11t_gost.h
%include "pkcs11t_gost.h"

перед оператором
%include "pkcs11lib.h"

Но это еще не всё. В методе getMechanismList (script PKCS11/__init__.py) заблокирован вывод механизмов чей код больше CKM_VENDOR_DEFINED (именно об этом и пишет автор проекта PyKCS11) (0x80000000L). Заметим, что ГОСТ-овые константы для новых алгоритмов попадают под это ограничение. Необходимо его снять хотя бы для ГОСТ-ов, заменим код метода getMechanismList на новый:
    def getMechanismList(self, slot):        """        C_GetMechanismList        :param slot: slot number returned by :func:`getSlotList`        :type slot: integer        :return: the list of available mechanisms for a slot        :rtype: list        """        mechanismList = PyKCS11.LowLevel.ckintlist()        rv = self.lib.C_GetMechanismList(slot, mechanismList)        if rv != CKR_OK:            raise PyKCS11Error(rv)        m = []#Правки для ГОСТ#define NSSCK_VENDOR_PKCS11_RU_TEAM 0xd4321000         for x in range(len(mechanismList)):            mechanism = mechanismList[x]            if mechanism >= CKM_VENDOR_DEFINED:                if mechanism >= CKM_VENDOR_DEFINED and mechanism < 0xd4321000:                    k = 'CKM_VENDOR_DEFINED_0x%X' % (mechanism - CKM_VENDOR_DEFINED)                    CKM[k] = mechanism                    CKM[mechanism] = k            m.append(CKM[mechanism])        return m#ORIGINAL#        for x in range(len(mechanismList)):#            mechanism = mechanismList[x]#            if mechanism >= CKM_VENDOR_DEFINED:#                k = 'CKM_VENDOR_DEFINED_0x%X' % (mechanism - CKM_VENDOR_DEFINED)#                CKM[k] = mechanism#                CKM[mechanism] = k#            m.append(CKM[mechanism])#        return m


Отметим также, что несмотря на то, что в модуль включены все механизмы, которые определены во включаемых файлах pkcs11t.h и pkcs11t_gost.h для pkcs11 v.2.40, все эти механизмы могут быть выполнены. Проблема состоит в том, что для некоторых из них требуется определенная структура параметров. Это, в частности, относится к механизму CKM_RSA_PKCS_OAEP, которому требуются параметры в виде структуры CK_RSA_PKCS_OAEP_PARAMS, и механизму CKM_PKCS5_PBKD2, который ждет параметров в виде структуры CK_PKCS5_PBKD2_PARAMS. Есть и другие механизмы. Но поскольку автор реализовал отдельные структуры для отдельных механизмов (для того же CKM_RSA_PKCS_OAEP), то не составит труда реализовать поддержку структур параметров и для других механизмов. Так, если кому потребуется работа с контейнером PKCS#12, то придется реализовать поддержку структуры CK_PKCS5_PBKD2_PARAMS.
Всё это относится к довольно сложным криптографическим механизмам.
А вот всё то, что касается хэширования, формирования проверки электронной подписи, наконец, шифрования, то всё работает замечательно. Но для начала надо собрать проект

II. Сборка обертки PyKCS11 с поддержкой ГОСТ-ов


Она ничем не отличается от сборки родной обёртки PkCS11 за исключением того, что исходный код необходимо получить здесь.
Далее следуем инструкции по сборке и установке пакета PyKCS11.
Для тестирования потребуется токен с поддержкой российской криптографии. Здесь мы имеем в виду ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012. Это может быть как аппаратный токен, например RuTokenECP-2.0, так и программные или облачные токены.
Установить программный токен или получить доступ к облачному токену можно, воспользовавшись утилитой cryptoarmpkcs.
Скачать утилиту cryptoarmpkcs можно здесь.
Скачать утилиту cryptoarmpkcs можно здесь.

После запуска утилиты необходимо зайти на вкладку Создать токены:

image

На вкладке можно найти инструкции для получения и установки токенов.

II. Тестирование российских алгоритмов

Для тестирования можно использовать скрипты, которые лежат в папке testGost:
  • ckm_kuznyechik_cbc.py
  • ckm_gostr3411_12_256.py
  • ckm_gostr3410_with_gostr3411_12_256.py
  • ckm_gostr3410_512.py

Для тестирования исходные данные брались как из соответствующих ГОСТ-ов, так и из рекомендаций ТК-26.
В данных скриптах тестируются следующие механизмы:
1. Генерация ключевых пар:
  • CKM_GOSTR3410_512_KEY_PAIR_GEN (ГОСТ Р 34.10-2012 с длиной ключа 1024 бита)
  • CKM_GOSTR3410_KEY_PAIR_GEN (ГОСТ Р 34.10-2012 с длиной ключа 512 бит)

2. Формирование и проверка электронной подписи:
  • CKM_GOSTR3410
  • CKM_GOSTR3410_512
  • CKM_GOSTR3410_WITH_GOSTR3411_12_256

3. Хэширования:
  • CKM_GOSTR3411_12_256

4. Шифрование/расшифровка
  • CKM_KUZNYECHIK_CBC


Генерация ключевых пар позволяет владельцу токена получить закрытый ключ, которым он может подписать, например, запрос на сертификат. Запрос на сертификат может быть отправлен в удостоверяющий центр и там по нему могут выдать сертификат. Владелец сертификата может импортировать его на токен, где хранится закрытый ключ. Теперь у владельца токена есть личный сертификат с закрытым ключом, который он может использовать для подписи документы.
Ну а если ему требуется особый режим секретности, то он может зашифровать документ по одному из алгоритмов, а именно Магме или Кузнечику. Всё это конечно в том случае, если сам токен поддерживает эти механизмы, пакет PyKCS11 является всего лишь посредником.
На этом наше повествование, связанное с поддержкой в Python токенов с российской криптографией заканчивается.
Подробнее..

Памятка для удостоверяющих центров и других участников PKI

26.04.2021 14:21:23 | Автор: admin

Памятка для удостоверяющих центров и других участников PKI

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

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

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

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

В этом посте я хочу рассказать, с какими критическими проблемами и нарушениями в работе УЦ часто приходится сталкиваться, а также о том, как их избежать.

У полноправного участника Public Key Infrastructure, должна быть информационная система со встроенными СКЗИ, которая позволяет вести электронный документооборот с клиентами и партнерами, обмениваясь с ними документами с электронной подписью (ЭП) или зашифрованными данными.

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

В частности, для сертификата партнера строится путь сертификации - цепочка сертификатов, от его конечного пользовательского, на котором проверилась ЭП, до корневого центра сертификации.

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

Для квалифицированных сертификатов также выполняются проверки согласно 63-ФЗ Об электронной подписи и Приказа ФСБ РФ 795. Контролируется наличие и правильность заполнения всех необходимых атрибутов в сертификате пользователя.

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

Сбои и некорректная работа УЦ в части публикации CRL

В сертификатах есть атрибут CDP - CRL Distribution Points, в нем УЦ публикует ссылки на свой список отозванных сертификатов - Certificate Revocation List

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

CRL тоже подписан ЭП удостоверяющего центра, что дает дополнительную защиту от подмены и атак посредника Man in the middle при его загрузке по открытому каналу. Он содержит атрибуты с периодом своего действия и серийные номера отозванных сертификатов.

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

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

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

То же самое касается контроля клиентских и серверных сертификатов, которые используются для построения защищенного канала связи TLS ГОСТ или TLS RSA по протоколу HTTPS. Если системам партнеров не удается проверить их на отзыв, то защищенное и 100% доверенное соединение партнеры установить между собой не смогут.

Какие сбои и нарушения здесь может допустить УЦ?

1. Перенаправление ссылок (Redirect)

УЦ опубликовал в сертификате конкретный URL, но на сервере, где этот ресурс опубликован, происходит перенаправление клиента на другой URL.

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

private static final String ATTENTION_CRL_REDIRECT_DETECTED = "Attention CRL redirect detected: ";    private static final String LOCATION = "Location";   URL url = new URL(crlURL);        InputStream crlStream = null;        URLConnection connection = url.openConnection();        String redirect = connection.getHeaderField(LOCATION);        if (redirect != null) {            throw new DownloadCRLException(                    ATTENTION_CRL_REDIRECT_DETECTED + crlURL + STRING_DIRECTION + redirect);        }

2. HTTPS в CDP атрибуте сертификата и ни одной общедоступной ссылки

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

Попадались сертификаты с https://, ldap:// или защищенный SFTP, также были просто URL с IP адресами из внутренней подсети. Все эти ссылки допустимы при наличии хотя бы одной ссылки HTTP или FTP (без логина и пароля) доступной из сети Internet всем.

Почему HTTPS к свободным не относится?

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

Другие информационные системы могут не иметь такого хранилища с предустановленными корневыми сертификатами и не обязаны поднимать контекст защищенного соединения к HTTPS-ссылкам.

Просто невозможно во все системы установить все корни для всего многообразия УЦ, выпускающих SSL/TLS-сертификаты.

По понятным причинам информационные системы также не могут знать логин и пароль от FTP и не будут иметь доступ к внутренней службе Active Directory по LDAP-протоколу.

Поэтому принято, что CRL публикуется в свободном доступе.

3. HTTP перенаправление (redirect) на HTTPS

Это гибридная ситуация, с которой приходилось сталкиваться, состоящая из приведенных выше пунктов 1 и 2.

Как такое возможно?

Сайт компании, где УЦ публикует свои списки отзыва, или просто веб-сервер, который используется удостоверяющим центром для этих целей, запущен, например, на Nginx.

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

server {    listen 80 default_server;    listen [::]:80 default_server;    server_name _;    return 301 https://$host$request_uri;}

Получается, что в сертификате приведен URL с http://, а системы, которые чувствительны к такому факту подмены подписанной информации из сертификата и справедливо защищаются от атак посредников, перестают загружать списки отзыва данного УЦ, пока администратор не настроит на сайте исключения для CRL.

4. Фильтрация по User Agent

Данная проблема и нарушение доступа к спискам отзыва сильно перекликается с приведенной в пункте 3.

Тот же администратор сайта, на том же Nginx включает фильтрацию по User Agent. Например, все системы на Java будут получать ошибку HTTP 403 при обращении к ресурсу.

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

if ($http_user_agent = "Mozilla/5.0 (Linux; Android 4.2.2; SGH-M919 Build/JDQ39) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.169 Mobile Safari/537.22"){    return 403;}if  ($http_user_agent ~* "^Java"){ return 403; }

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

5. Просроченный CRL

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

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

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

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

Были случаи, когда по каким-то причинам УЦ своевременно не обновлял CRL.

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

6. Сбои на сетевом и транспортном уровне

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

В сертификате, выпущенном УЦ, может быть прописано два URL с http:// и разными host именами. Такой подход правильный, он позволяет иметь резерв и всегда держать одну ссылку в доступе, если требуется провести какие-то работы на другом сервере.

Но вот незадача. Вызывающая система вдруг начинает получать IOException: ConnectionTimeOut при попытке подключения к одной из ссылок. Вторая ссылка при этом работает и отдает CRL. А вызывающая система все равно начинает замедляться на настроенное в ней время, например, ConnectionTimeOut=15000 mSec, потому что проверяет обе ссылки, и ей приходится ждать ответа от недоступной в настоящий момент.

А если в CDP сертификата четыре, пять разных ссылок на CRL и при этом две или три из них оказываются недоступны с ConnectionTimeOut?

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

А что, если обмен нашей информационной системы идет с этим УЦ или партнером, организацией, аффилированной с данным УЦ? И система партнера имеет свой таймаут на вызов нашей информационной системы, который заведомо меньше того времени, которое наша система тратит на проверку их сертификата?

Получается коллизия.

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

Почему может происходить ConnectionTimeOut?

Как вариант, это регламентные работы, сетевая атака или повышенная нагрузка на сайт УЦ, что привело к неконсистентному состоянию:

  • какой-то брандмауэр, файрвол на пути, который просто начал съедать сетевые пакеты, не сообщая отправителю такие вещи, как "No Route to host"

  • началась потеря пакетов из-за неправильной конфигурации сети или перегрузки линии

  • слишком много запросов, перегружающих сервер

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

Как с этим справляться?

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

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

Если точка публикации будет корректно отключена, то вызывающая система, мгновенно получив от этой ссылки, например, IOException Connection Refused: connect, сразу перейдет к загрузке по следующему URL.

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

Чем должны руководствоваться УЦ при публикации CRL

RFC 5280 Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile

Спецификацией RFC 5280 IETF и стандартом X.509 ITU-T, разработанными Инженерным советом Интернета и Международным консультационным комитетом по телефонии и телеграфии.

В частности, пунктом 8. Security Considerations из RFC 5280

When certificates include a cRLDistributionPoints extension with an https URI or similar scheme, circular dependencies can be introduced. The relying party is forced to perform an additional path validation in order to obtain the CRL required to complete the initial path validation! Circular conditions can also be created with an https URI (or similar scheme) in the authorityInfoAccess or subjectInfoAccess extensions. At worst, this situation can create unresolvable dependencies.

CAs SHOULD NOT include URIs that specify https, ldaps, or similar schemes in extensions. CAs that include an https URI in one of these extensions MUST ensure that the server's certificate can be validated without using the information that is pointed to by the URI. Relying parties that choose to validate the server's certificate when obtaining information pointed to by an https URI in the cRLDistributionPoints, authorityInfoAccess, or subjectInfoAccess extensions MUST be prepared for the possibility that this will result in unbounded recursion.

УЦ не должны включать HTTPS или LDAP-ссылки для публикации своих списков отзыва.

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

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

Другими словами, клиент и сервер будут пытаться поднять защищенное HTTPS-соединение друг с другом. Для этого им потребуется проверить сертификаты на отзыв. А чтобы это сделать, тоже нужно поднять защищенное соединение по HTTPS-ссылке к CRL, которую УЦ неосмотрительно опубликовал в атрибуте сертификата.

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

Протокол онлайн-проверки статуса сертификата OCSP - Online Certificate Status Protocol.

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

А для работы с сервером OCSP они должны включать еще и расширение OCSP Server Client.

Но это материал для отдельнойстатьи.

Обязательные атрибуты квалифицированных сертификатов

Состав квалифицированного сертификата регулируется Федеральным законом "Об электронной подписи" от 06.04.2011 N 63-ФЗ и Приказом ФСБ РФ от 27 декабря 2011 г. N 795 "Об утверждении Требований к форме квалифицированного сертификата ключа проверки электронной подписи".

Несколько раз встречались квалифицированные сертификаты проверки подписи юридических лиц, выпущенные аккредитованным УЦ, в которых в поле Subject - субъект сертификации отсутствовал атрибут L Местоположение.

Контроль квалифицированных сертификатов нашей системы отвергал данный сертификат и документы с ЭП партнера.

Удостоверяющий центр данную ситуацию комментировал так:

атрибут L для юридических лиц, зарегистрированных в г. Москве, не проставляется согласно 63-ФЗ и Приказа 795

На конкретный пункты Закона и Приказа в УЦ не ссылались.

Собственный повторный анализ юридических аспектов показал:

63-ФЗ от 06.04.2011 "Об электронной подписи"

Статья 14. Сертификат ключа проверки электронной подписи

2. Сертификат ключа проверки электронной подписи должен содержать следующую информацию:

2) фамилия, имя и отчество (если имеется) - для физических лиц, наименование и место нахождения - для юридических лиц или иная информация, позволяющая идентифицировать владельца сертификата ключа проверки электронной подписи;

Статья 17. Квалифицированный сертификат

2. Квалифицированный сертификат должен содержать следующую информацию:

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

Приказ ФСБ РФ от 27 декабря 2011 г. 795

III. Требования к порядку расположения полей квалифицированного сертификата

5) stateOrProvinceName (наименование штата или области).

В качестве значения данного атрибута имени следует использовать текстовую строку, содержащую наименование соответствующего субъекта Российской Федерации. Объектный идентификатор типа атрибута stateOrProvinceName имеет вид 2.5.4.8;

6) localityName (наименование населенного пункта).

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

7) streetAddress (название улицы, номер дома).

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

В сертификате партнера в имени субъекта сертификации были указаны: stateOrProvinceName (наименование штата или области), streetAddress (название улицы, номер дома).

И не указано localityName (наименование населенного пункта).

locality - Местонахождение

В Законе 63-ФЗ и Приказе 795 нет информации, что для города Москва не нужно заполнять атрибут locality - Местонахождение.

Наоборот в обоих документах на русском языке применяется термин место нахождения, чему соответствует атрибут localityName ( 2.5.4.7)

После данного разбора удалось найти документ ФСБ РФ ИЗВЕЩЕНИЕ ОБ ИСПОЛЬЗОВАНИИ АТРИБУТА ИМЕНИ LOCALITYNAME ПОЛЯ SUBJECT В СТРУКТУРЕ КВАЛИФИЦИРОВАННОГО СЕРТИФИКАТА КЛЮЧА ПРОВЕРКИ ЭЛЕКТРОННОЙ ПОДПИСИ

Согласно части 2.2 статьи 18 Закона об ЭП для заполнения квалифицированного сертификата в соответствии с частью 2 статьи 17 Закона об ЭП аккредитованный удостоверяющий центр запрашивает и получает из государственных информационных ресурсов, в том числе, выписку из единого государственного реестра юридических лиц в отношении заявителя юридического лица.

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

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

Данное извещение с разъяснениями регулятора, как правильно заполнять атрибут L в квалифицированном сертификате юридического лица, также было направлено в аккредитованный УЦ.

Прошу использовать данную информацию в работе.

Желаю всем участникам PKI удачи и успехов!

Подробнее..

Обзор процедуры анонимизации системы дистанционного электронного голосования

10.09.2020 16:11:14 | Автор: admin
В предыдущих публикациях мы остановились на том, что в рассматриваемой нами системе дистанционного электронного голосования для обеспечения тайны голосования и анонимизации избирателя используется криптографический алгоритм слепой электронной подписи. В этой статье мы рассмотрим его более подробно.

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

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

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

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

Теперь перейдем к тому, что такое слепая подпись и как она может помочь нам при анонимизации.

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



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

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

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

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

Сначала на устройстве избирателя открытый ключ должен быть замаскирован. Маскировка это выполнение отдельных математических действий на устройстве пользователя. Представьте, что вы задумали некоторое случайное число от 1 до 100, потом задумали второе случайное от 1 до 10 и третье, от 10 до 50, первоначально задуманное число возвели в степень второго числа, и разделили без остатка на третье. Полученный результат сообщили окружающим. Вам не составит труда восстановить первоначальное число, так как вы знаете последовательность действий и задуманные вами числа. Но окружающие это сделать не смогут.

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

Описанный алгоритм широко используется в протоколах тайного голосования. В системе дистанционного электронного голосования на данный момент для слепой подписи используется алгоритм RSA с длиной ключа 4096 бит.

В общем виде процедура анонимизации выглядит следующим образом.

  1. При создании голосования создается отдельная ключевая пара валидатора, открытый ключ записывается в блокчейн. На каждое голосование создается уникальная ключевая пара.
  2. Пользователь идентифицируется в системе идентификации (в данном случае, в ЕСИА), и предоставляет разрешение на передачу своих идентификационных данных из системы идентификации в ПТК ДЭГ.
  3. Компонент Список избирателей ПТК ДЭГ проверяет наличие пользователя в списке избирателей.
  4. На устройстве пользователя создаются его личные ключи закрытый и открытый, известные только ему.
  5. На устройстве пользователя открытый ключ маскируется
  6. Вместе с идентификационными данными и замаскированным открытым ключом пользователь обращается к компоненту Список избирателей
  7. Компонент еще раз проверяет наличие пользователя в списке и факт того, что он не получал подпись ранее
  8. Если все проверки успешны, происходит подпись ключа
  9. Факт подписи ключа записывается в блокчейн
  10. Пользователь на своем устройстве снимает маску с открытого ключа и получает закрытый ключ, открытый ключ и подпись на открытый ключ, при этом все ключи известны только ему.
  11. После этого пользователь переводится в анонимную зону на отдельный сайт edg2020.gov.ru, где его невозможно идентифицировать (например, до перехода он может подключить VPN или сменить интернет-провайдера, полностью изменив IP-адрес)
  12. Прием бюллетеня будет зависеть только от того, пройдет ли проверку подпись валидатора и не был ли такой ключ использован ранее.


Далее приведем описание алгоритма с точки зрения криптографии.
Параметры подписи и обозначения:




M в формате padding FDN для подписи.
Подробнее..

Как у меня увели домен на reg.ru

09.03.2021 16:05:49 | Автор: admin

Хочу поделиться радостной новостью, если у вас есть домен на reg.ru или его партнерах 2domains.ru или других, то возможно это не надолго, в смысле есть он у вас не надолго.

Как-то раз сижу я за работой и тут мне на почту пишет юзер моего сайта, говорит что-то твой сайт (http://personeltest.ru/away/lines-98.ru) давно не открывается.

Действительно, захожу я туда пишу хостеру, тот говорит ошибка в DNS. Захожу в DNS записи, а они пустые и не редактируются. Смотрю информацию по домену - домен уже у другого регистратора, был reg.ru стал webnames.ru.

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

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

Reg.ru:

Здравсвуйте!

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

Webnames.ru:

Здравствуйте!

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

Мы располагаем информацией о домене только с момента его переноса к нам - с 23 февраля 2021г. О смене регистратора мы уведомили текущего администратора (лицо, чьи данные на тот момент были внесены в реестр), проверили копии его документов и получили его согласие с переносом. С момента переноса нарушений Правил регистрации мы не выявили, поэтому у нас нет оснований что-либо делать с этим доменом.

Пути выхода из сложившийся ситуации всего два:
1) Договориться с текущим администратором домена о передаче домена Вам.
2) Получить решение суда, которое обяжет нас передать домен тому лицу, на которое укажет суд.

Так как я нахожу в другой стране, то вариантов у меня не так много. Могу только всем посоветовать, не регистрировать домен у регистратора, который может отдать ваш домен даже не уведомив вас по почте.

Убыток где-то составляет 30к в месяц, сайт перенес пока на http://color-lines-98.ru но раскручивать его теперь придется по новой, было написано даже андройд приложение которое все это время не работало пока сайт переносился.

К слову это не первый раз когда у меня хотели увести домен, купить его, скопировать игру, на просторах интернета можно увидеть несколько копий моего сайта, сделаю им рекламу:

http://color-lines.ru/

http://game-shariki.ru/shariki-linii

http://lines98.org.ua/color-lines.html

ну и теперь к нему можно добавить http://lines-98.ru.

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

Спасибо reg.ru, спасибо за внимание.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru