В предыдущей статье «Токены PKCS#11: сертификаты и закрытые ключи» мы рассмотрели как можно однозначно связать тройку Сертификат x ПубличныйКлюч x ПриватныйКлюч, хранимую на токене/смаркарте с интерфейсом PKCS#11 v.2.40. В данной статье мы поговорим о генерации ключевой пары. Опираться мы будем, как и прошлый раз, на «ГОСТ Р 34.10-2012 Информационная технология. Криптографическая защита информации. Процессы формирования и проверки электронной цифровой подписи».
Ключевая пара включает в себя два ключа:
Следует помнить, что закрытый и открытый ключи это не только их значения (для открытого ключа ГОСТ Р 34.10-2001 это 512 бит), но и параметры схемы цифровой подписи (п. 5.2 ГОСТ Р 34.10-2012). В дальнейшем параметры схемы цифровой подписи для простоты будем называть параметрами (криптопараметрами) ключевой пары.
Открытый ключ подписи вычисляется, как значение некоторой функции от закрытого ключа, но знание открытого ключа не дает возможности определить закрытый ключ.
Для ключевых пар ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012 с длиной закрытого ключа 256 бит (соответственно, публичный ключ – 512 бит) определены следующие криптопараметры:
Для ключевых пар ГОСТ Р 34.10-2012 с длиной закрытого ключа 512 бит (соответственно, публичный ключ – 1024 бита) определены следующие криптопараметры («Информационная технология. Криптографическая защита информации. Параметры эллиптических кривых для криптографических алгоритмов и протоколов»):
Состав криптопараметров определен в п.5.2 в ГОСТ Р 34.10-2012. В этот состав входит простое число q — порядок подгруппы группы точек эллиптической кривой:
И именно оно определяет длину закрытого/открытого ключей и корректность закрытого ключа:
— длина закрытого ключа 256 бит;
— длина закрытого ключа 512 бит.
И так, открытый ключ получается из закрытого ключа.
Для получения закрытого ключа сначала необходимо решить какой длины будет закрытый ключ (256 или 512 бит), затем определиться с криптопараметрами ключевой пары. Теперь берем датчик случайных чисел и получаем случайное число соответствующей длины. Собственно это случайное число и должно стать значением d закрытого ключа (ключом подписи d). Это значение должно удовлетворять следующему правилу:
0 < d < q, где q – простое число из криптопараметров.
Что делать, если это условие не выполняется? Если d == 0, то просто сгенерировать новое случайное число. В противном случае достаточно бывает взять остаток от деления на цело значения d, которое превышает q, на q (d % q). Остаток и станет значением закрытого ключа.
Именно поэтому регулятор (ФСБ России) предъявляет особые требования к датчику случайных чисел.
В качестве примера основного источника для заполнения буфера:
В качестве дополнительных источников для заполнения данного буфера могут выступать:
Таким образом, чтобы токен/смарткарта PKCS#11 могли генерировать внутри себя ключевую пару, необходимо наличие токен/смарткарта встроенного аппаратного датчика случайных чисел, соответствующего требованиям регулятора. И только тогда можно говорить о неизвлекаемости закрытого ключа.
Для генерации ключевой пары используется фунция C_GenerateKeyPair. В зависимости от того, какую ключевую пару (с какой длиной закрытого ключа 256 или 512 бит) мы генерируем, в ней будет использоваться соответствующий механизм:
При генерации ключевой пары задаются ее атрибуты, например, криптопараметры:
Это прежде атрибут CKA_SENSITIVE, отвечающий за возможность получения значения закрытого ключа. Если значение атрибута CKA_SENSITIVE установлено в CK_TRUE, то закрытый ключ не может быть извлечен из токена в открытом виде. Второй атрибут CKA_EXTRACTABLE позволяет получать закрытый ключ в зашифрованном виде. Для этого его необходимо установить CK_TRUE.
Установка атрибута CKA_SENSITIVE в CK_TRUE, а атрибута CKA_EXTRACTABLE в CK_FALSE при генерации ключевой пары делает закрытый ключ абсолютно неизвлекаемым. Возможность определять является ли ключ экспортабельным имеется в браузере Redfox:
Кто-то скажет, — а что если изменить значения этих атрибутов. Как правило этого сделать нельзя, защиту понизить нельзя, также как «нельзя понижать градус». Точно также можно сделать неизвлекаемым закрытый ключ после его импорта на токен (если конечно токен/смарткарта разрешают импорт). После создания (или во время создания) объекта CKO_PRIVATE_KEY необходимо установить CKA_SENSITIVE=CK_TRUE, а атрибута CKA_EXTRACTABLE=CK_FALSE.
В последнем случае (при импорте) следует иметь в виду, что хотя закрытый ключ и стал неизвлекаемым, он появился со стороны (например, из PKCS#12), и гарантии, что нет еще где-то его дубликата нету.
И вот здесь не мешало бы напомнить тебе, уважаемый читатель, что безопасность обеспечивается только КОМПЛЕКСОМ организационных и технических мероприятий. Поэтому не получится латать дыры в организационной безопасности за счет технических средств и наоборот — все должно быть органично согласовано. В том числе, и при доступе к значению закрытого ключа.
Убедиться, что на токен/смарткарте находятся полноценные объекты PKCS#11 (CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_CERTIFICATE), которые участвуют в криптографических операциях на самом токене удобно с помощью доступной для свободного скачивания утилиты p11conf:
Для того, чтобы посмотреть какие объекты находятся на токене достаточно выполнить команду вида:
Если такие объекты отсутствуют на токене, а говорят, что используется токен PKCS#11 с неизвлекаемым ключом, то это скорей всего не так. Скорей всего токен используется просто как флэшка с PIN-кодом, а сертификат и ключи хранятся как объекты CKO_DATA.
И наконец, для того, чтобы посмотреть не только какие типы объектов хранятся на токене, а объекты со всеми атрибутами необходимо использовать дополнительно флаг –d:
Все сказанное здесь справедливо для токена/смарткарты с интерфейсом PKCS#11, включая облачный токен.
В заключение напомним, что токены/смаркарты с интерфейсом PKCS#11 широко используются в проектах Mozilla (браузеры, почтовые клиенты), в браузерах Chrome от Google и других проектах. Если говорить о России, то токены/смаркарты с интерфейсом PKCS#11успешно используются для доступа на портал Госуслуг.
Итак, что такое ключевая пара?
Ключевая пара включает в себя два ключа:
- Закрытый ключ/Приватный /Private key — ключ, известный только своему владельцу. Только сохранение владельцем/пользователем в тайне своего закрытого ключа гарантирует невозможность подделки злоумышленником документа и цифровой подписи от имени заверяющего;
- Открытый ключ/Публичный ключ/ Public key — ключ, который может быть опубликован в сертификате и используется для проверки подлинности подписанного документа, а также для предупреждения мошенничества со стороны заверяющего лица в виде отказа его от подписи документа.
Следует помнить, что закрытый и открытый ключи это не только их значения (для открытого ключа ГОСТ Р 34.10-2001 это 512 бит), но и параметры схемы цифровой подписи (п. 5.2 ГОСТ Р 34.10-2012). В дальнейшем параметры схемы цифровой подписи для простоты будем называть параметрами (криптопараметрами) ключевой пары.
Открытый ключ подписи вычисляется, как значение некоторой функции от закрытого ключа, но знание открытого ключа не дает возможности определить закрытый ключ.
Для ключевых пар ГОСТ Р 34.10-2001 и ГОСТ Р 34.10-2012 с длиной закрытого ключа 256 бит (соответственно, публичный ключ – 512 бит) определены следующие криптопараметры:
- id-GostR3410-2001-CryptoPro-A-ParamSet;
- id-GostR3410-2001-CryptoPro-B-ParamSet;
- id-GostR3410-2001-CryptoPro-C-ParamSet;
- id-GostR3410-2001-CryptoPro-XchA-ParamSet;
- id-GostR3410-2001-CryptoPro-XchB-ParamSet.
Для ключевых пар ГОСТ Р 34.10-2012 с длиной закрытого ключа 512 бит (соответственно, публичный ключ – 1024 бита) определены следующие криптопараметры («Информационная технология. Криптографическая защита информации. Параметры эллиптических кривых для криптографических алгоритмов и протоколов»):
- id-tc26-gost-3410-2012-512-paramSetA;
- id-tc26-gost-3410-2012-512-paramSetB.
Состав криптопараметров определен в п.5.2 в ГОСТ Р 34.10-2012. В этот состав входит простое число q — порядок подгруппы группы точек эллиптической кривой:
И именно оно определяет длину закрытого/открытого ключей и корректность закрытого ключа:
— длина закрытого ключа 256 бит;
— длина закрытого ключа 512 бит.
И так, открытый ключ получается из закрытого ключа.
А откуда берется закрытый ключ?
Для получения закрытого ключа сначала необходимо решить какой длины будет закрытый ключ (256 или 512 бит), затем определиться с криптопараметрами ключевой пары. Теперь берем датчик случайных чисел и получаем случайное число соответствующей длины. Собственно это случайное число и должно стать значением d закрытого ключа (ключом подписи d). Это значение должно удовлетворять следующему правилу:
0 < d < q, где q – простое число из криптопараметров.
Что делать, если это условие не выполняется? Если d == 0, то просто сгенерировать новое случайное число. В противном случае достаточно бывает взять остаток от деления на цело значения d, которое превышает q, на q (d % q). Остаток и станет значением закрытого ключа.
Именно поэтому регулятор (ФСБ России) предъявляет особые требования к датчику случайных чисел.
В качестве примера основного источника для заполнения буфера:
- случайными цифрами можно привести:
- регистр TSC процессора – счетчик тактов процессора;
- счетчик времени GTC;
- автоинкрементируемый счетчик в отдельном потоке;
- стандартная функция rand();
- координаты мыши.
В качестве дополнительных источников для заполнения данного буфера могут выступать:
- Счетчик времени работы процесса в пользовательском режиме;
- Таймер высокого разрешения Windows.
Таким образом, чтобы токен/смарткарта PKCS#11 могли генерировать внутри себя ключевую пару, необходимо наличие токен/смарткарта встроенного аппаратного датчика случайных чисел, соответствующего требованиям регулятора. И только тогда можно говорить о неизвлекаемости закрытого ключа.
Для генерации ключевой пары используется фунция C_GenerateKeyPair. В зависимости от того, какую ключевую пару (с какой длиной закрытого ключа 256 или 512 бит) мы генерируем, в ней будет использоваться соответствующий механизм:
- CKM_GOSTR3410_KEY_PAIR_GEN для ключевой пары с закрытым ключом в 256 бит;
- CKM_GOSTR3410_512_KEY_PAIR_GEN для ключевой пары с закрытым ключом в 512 бит.
При генерации ключевой пары задаются ее атрибуты, например, криптопараметры:
Нас интересуют атрибуты извлекаемости закрытого ключа.
Это прежде атрибут CKA_SENSITIVE, отвечающий за возможность получения значения закрытого ключа. Если значение атрибута CKA_SENSITIVE установлено в CK_TRUE, то закрытый ключ не может быть извлечен из токена в открытом виде. Второй атрибут CKA_EXTRACTABLE позволяет получать закрытый ключ в зашифрованном виде. Для этого его необходимо установить CK_TRUE.
Установка атрибута CKA_SENSITIVE в CK_TRUE, а атрибута CKA_EXTRACTABLE в CK_FALSE при генерации ключевой пары делает закрытый ключ абсолютно неизвлекаемым. Возможность определять является ли ключ экспортабельным имеется в браузере Redfox:
Кто-то скажет, — а что если изменить значения этих атрибутов. Как правило этого сделать нельзя, защиту понизить нельзя, также как «нельзя понижать градус». Точно также можно сделать неизвлекаемым закрытый ключ после его импорта на токен (если конечно токен/смарткарта разрешают импорт). После создания (или во время создания) объекта CKO_PRIVATE_KEY необходимо установить CKA_SENSITIVE=CK_TRUE, а атрибута CKA_EXTRACTABLE=CK_FALSE.
В последнем случае (при импорте) следует иметь в виду, что хотя закрытый ключ и стал неизвлекаемым, он появился со стороны (например, из PKCS#12), и гарантии, что нет еще где-то его дубликата нету.
И вот здесь не мешало бы напомнить тебе, уважаемый читатель, что безопасность обеспечивается только КОМПЛЕКСОМ организационных и технических мероприятий. Поэтому не получится латать дыры в организационной безопасности за счет технических средств и наоборот — все должно быть органично согласовано. В том числе, и при доступе к значению закрытого ключа.
Убедиться, что на токен/смарткарте находятся полноценные объекты PKCS#11 (CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_CERTIFICATE), которые участвуют в криптографических операциях на самом токене удобно с помощью доступной для свободного скачивания утилиты p11conf:
$ /usr/local/bin64/p11conf -h
usage: /usr/local/bin64/p11conf [-hitsmIupPred] -A APIpath [-c slotID -U userPin -S SOPin -n newPin -L label]
-h display usage
-i display PKCS#11 library info
-s display slot(s) info (-c slotID is optional)
-t display token(s) info (-c slotID is optional)
Others must use -c slotID
-m display mechanism list
-I initialize token
-u initialize user PIN
-p set the user PIN
-P set the SO PIN
-r remove all objects
-e enumerate objects
-d dump all object attributes
Copyright(C) 2011-2016
$
Для того, чтобы посмотреть какие объекты находятся на токене достаточно выполнить команду вида:
bash-4.3$ /usr/local/bin64/p11conf -A /usr/local/lib64/libls11sw2016.so -c 0 -e
Enter user PIN: ********
Token objects:
1: CKO_PRIVATE_KEY
label: 'LS11SW2016:ООО;Маслов А.А.;0x23855(145493)'
2: CKO_PUBLIC_KEY
label: 'LS11SW2016:ООО;Маслов А.А.;0x23855(145493)'
3: CKO_CERTIFICATE
label: 'LS11SW2016:ООО;Маслов А.А.;0x23855(145493)'
…
OK
bash-4.3$
Если такие объекты отсутствуют на токене, а говорят, что используется токен PKCS#11 с неизвлекаемым ключом, то это скорей всего не так. Скорей всего токен используется просто как флэшка с PIN-кодом, а сертификат и ключи хранятся как объекты CKO_DATA.
И наконец, для того, чтобы посмотреть не только какие типы объектов хранятся на токене, а объекты со всеми атрибутами необходимо использовать дополнительно флаг –d:
bash-4.3$ /usr/local/bin64/p11conf -A /usr/local/lib64/libls11sw2016.so -c 0 –e -d
Enter user PIN: ********
Token objects:
1: CKO_PRIVATE_KEY
label: 'LS11SW2016:ООО;Маслов А.А.;0x23855(145493)'
==================================
Object handle: 0x1
----------------------------------
CKA_CLASS
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
CKA_TOKEN
0x01,
CKA_PRIVATE
0x01,
CKA_LABEL
0x4c, 0x53, 0x31, 0x31, 0x53, 0x57, 0x32, 0x30,
0x31, 0x36, 0x3a, 0xd0, 0x9e, 0xd0, 0x9e, 0xd0,
0x9e, 0x20, 0xd0, 0x9b, 0xd0, 0x98, 0xd0, 0xa1,
0xd0, 0xa1, 0xd0, 0x98, 0x2d, 0xd0, 0xa1, 0xd0,
0xbe, 0xd1, 0x84, 0xd1, 0x82, 0x3b, 0xd0, 0x9c,
0xd0, 0xb0, 0xd1, 0x81, 0xd0, 0xbb, 0xd0, 0xbe,
0x20, 0xd0, 0x90, 0x2e, 0xd0, 0x90, 0x2e, 0x3b,
0x30, 0x78, 0x32, 0x33, 0x38, 0x35, 0x35, 0x28,
0x31, 0x34, 0x35, 0x34, 0x39, 0x33, 0x29,
CKA_VALUE: attribute sensitive
CKA_KEY_TYPE
0x03, 0x10, 0x32, 0xd4, 0x00, 0x00, 0x00, 0x00,
CKA_SUBJECT
0x30, 0x81, 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06,
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x52, 0x55,
0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04,
0x03, 0x0c, 0x11, 0xd0, 0x9c, 0xd0, 0xb0, 0xd1,
0x81, 0xd0, 0xbb, 0xd0, 0xbe, 0x20, 0xd0, 0x90,
0x2e, 0xd0, 0x90, 0x2e, 0x31, 0x1c, 0x30, 0x1a,
0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x13, 0xd0,
0x9b, 0xd0, 0x98, 0xd0, 0xa1, 0xd0, 0xa1, 0xd0,
0x98, 0x2d, 0xd0, 0xa1, 0xd0, 0xbe, 0xd1, 0x84,
0xd1, 0x82, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09,
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
0x01, 0x16, 0x10, 0x61, 0x6d, 0x61, 0x73, 0x6c,
0x6f, 0x76, 0x40, 0x6c, 0x69, 0x73, 0x73, 0x69,
0x2e, 0x72, 0x75, 0x31, 0x31, 0x30, 0x2f, 0x06,
0x03, 0x55, 0x04, 0x08, 0x0c, 0x28, 0x35, 0x30,
0x20, 0x20, 0xd0, 0x9c, 0xd0, 0xbe, 0xd1, 0x81,
0xd0, 0xba, 0xd0, 0xbe, 0xd0, 0xb2, 0xd1, 0x81,
0xd0, 0xba, 0xd0, 0xb0, 0xd1, 0x8f, 0x20, 0xd0,
0xbe, 0xd0, 0xb1, 0xd0, 0xbb, 0xd0, 0xb0, 0xd1,
0x81, 0xd1, 0x82, 0xd1, 0x8c, 0x20,
CKA_ID
0x97, 0x46, 0x4e, 0xcc, 0x7c, 0xa9, 0xea, 0xb1,
0x0a, 0xda, 0xec, 0x10, 0xf4, 0x49, 0x7e, 0x7f,
0x2d, 0x71, 0x4b, 0xa7,
CKA_SENSITIVE
0x01,
. . .
CKA_GOSTR3410_PARAMS
0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02,
0x01, 0x02, 0x01,
CKA_GOSTR3411_PARAMS
0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01,
0x02, 0x03,
CKA_GOST28147_PARAMS
0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f,
0x01,
…
OK
bash-4.3$
Все сказанное здесь справедливо для токена/смарткарты с интерфейсом PKCS#11, включая облачный токен.
В заключение напомним, что токены/смаркарты с интерфейсом PKCS#11 широко используются в проектах Mozilla (браузеры, почтовые клиенты), в браузерах Chrome от Google и других проектах. Если говорить о России, то токены/смаркарты с интерфейсом PKCS#11успешно используются для доступа на портал Госуслуг.