Более двух лет прошло после выхода первого релиза библиотеки libgcrypt с поддержкой базовой российской криптографиии, а именно ГОСТ 28147-89, ГОСТ Р 34.11-94, ГОСТ Р 34.11-2012 (в реализации данной библиотеки STRIBOG256 и STRIBOG512), ГОСТ Р 34.10-2001 и ГОСТ Р 34.1-2012.
Однако практического применения, в отличие от OpenSSL с поддержкой российской криптографии, данная библиотека пока не находит. С чем это связано и куда двигаться?
Преимущество OpenSSL – это наличие утилиты командной строки openssl и поддержка в рамках одного проекта, подчеркиваем, в рамках одного проекта стандарта X.509, помимо ядра криптографии протоколов PKCS7, CMS, TLS, PKCS7 и других. Тоже самое можно сказать о библиотеке NSS (Nework Security System) и ее использовании в решениях Mozilla.
К сожалению, в самом проекте libgcrypt этого нет. Здесь на помощь приходят другие проекты прикладного уровня, которые используют эту библиотеку. Прежде всего, это проект GNU Privacy Guard (GnuPG, GPG), в рамках которого предоставляются инструментальные средства шифрования и цифровой подписи, соответствующие стандарту OpenPGP. В рамках этого проекта нас будет интересовать инструментальное средство gpgsm, которое используется для предоставления сервиса цифрового шифрования и электронной подписи (ЭП) на базе сертификатов X.509 и протокола CMS/PKCS7. GpgSM используется в основном в качестве движка при обработке электронной почты S/MIME, в частности, в почтовом клиенте KMail. Но если мы говорим о сертификатах, то нельзя не упомянуть о графической утилите управления сертификатвми X509 Kleopatra.
Так что же изменилось с выходом библиотеки libgcrypt-1.6.5 с точки зрения использования PKI (Public Key Infrastruture) с российской криптографией в повседневной жизни?
Решили начать с просмотра подписанного почтового сообщения. С почтового клиента Thunderbird поддержкой российской криптографии (http://soft.lissi.ru/about/news/2016/03/71/) было отправлено подписанное сообщение:
К сожалению, почтовый клиент KMail, получив это сообщение, не смог проверить ЭП:
Клеопатра также отказывалась признавать российские сертификаты. Мы приступили к анализу ситуации. Естественно, начали с библиотеки libgcrypt. Все тесты для российской криптографии в рамках проекта проходили успешно. Но анализ исходного кода показал, что в проекте для ГОСТ-криптографии используются только тестовые узлы замен для ГОСТ-28147-89 и ГОСТ Р 34.11-94, а также тестовые параметры алгоритма подписи ГОСТ Р 34.10-2001 и тестовые параметры алгоритма подписи ГОСТ Р 34.10-2012 с ключом 512. И первым делом пришлось добавить рабочие узлы замен и рабочие параметры алгоритмов подписи:
/* This static table defines all available curves, ecc-curvec.c */
static const ecc_domain_parms_t domain_parms[] =
{
{
/* (-x^2 + y^2 = 1 + dx^2y^2) */
"Ed25519", 256, 0,
MPI_EC_TWISTEDEDWARDS, ECC_DIALECT_ED25519,
"0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
"-0x01",
"-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
"0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
"0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
"0x6666666666666666666666666666666666666666666666666666666666666658"
},
. . .
{
"GOST2001-test", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x8000000000000000000000000000000000000000000000000000000000000431", // p
"0x0000000000000000000000000000000000000000000000000000000000000007", // a
"0x5fbff498aa938ce739b8e022fbafef40563f6e6a3472fc2a514c0ce9dae23b7e", // b
"0x8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3", // n(q)
"0x0000000000000000000000000000000000000000000000000000000000000002", // g_x
"0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8", // g_y
},
/*ORLOV*/
{
"GOST2001-A", 256, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd97", // p
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd94", // a
"0x00000000000000000000000000000000000000000000000000000000000000a6", // b
"0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893", // n(q)
"0x0000000000000000000000000000000000000000000000000000000000000001", // g_x
"0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14", // g_y
},
. . .
{
"GOST2012-test", 511, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
"f1d852741af4704a0458047e80e4546d35b8336fac224dd81664bbf528be6373", // p
"0x0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000007", // a
"0x1cff0806a31116da29d8cfa54e57eb748bc5f377e49400fdd788b649eca1ac4"
"361834013b2ad7322480a89ca58e0cf74bc9e540c2add6897fad0a3084f302adc", // b
"0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
"a82f2d7ecb1dbac719905c5eecc423f1d86e25edbe23c595d644aaf187e6e6df", // n(q)
"0x24d19cc64572ee30f396bf6ebbfd7a6c5213b3b3d7057cc825f91093a68cd762"
"fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a", // g_x
"0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
"c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e", // q_y
},
/*ORLOV*/
{
"GOST2012-512-A", 512, 0,
MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", // p
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4", // a
"0xE8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265"
"EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760", // b
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
"27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275", // n(q)
"0x0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000003", // g_x
"0x7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921"
"DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4", // q_y
},
. . .
{ NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL }
};
Также пришлось, естественно пришлось включать привязку параметров алгоритмов к их oid-ам (Идентификаторы объектов (OID) технического комитета по стандартизации «Криптографическая защита информации» (ТК 26):
/* This tables defines aliases for curve names, ecc-curves.c */
static const struct
{
const char *name; /* Our name. */
const char *other; /* Other name. */
} curve_aliases[] =
{
/*{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },*/
{ "Ed25519", "1.3.6.1.4.1.11591.15.1" },
. . .
/*ORLOV*/
{ "GOST2001-test", "1.2.643.2.2.35.0" },
{ "GOST2001-A", "1.2.643.2.2.35.1" },
{ "GOST2001-B", "1.2.643.2.2.35.2" },
{ "GOST2001-C", "1.2.643.2.2.35.3" },
{ "GOST2001-XA", "1.2.643.2.2.36.0"},
{ "GOST2001-XB", "1.2.643.2.2.36.1"},
{ "GOST2012-test", "1.2.643.7.1.2.1.2.0" },
{ "GOST2012-512-A", "1.2.643.7.1.2.1.2.1" },
{ "GOST2012-512-B", "1.2.643.7.1.2.1.2.2" },
{ NULL, NULL}
};
Это был тот минимум, с которого надо было начинать. Для всех алгоритмов, прежде всего ГОСТ Р 34.10, были прогнаны тестовые примеры (утилита benchmark, доработанная с учетом включения новых параметров. Полученные результаты были проверены на тестовых примерах ТК-26 с использованием ранее апробированных средств криптографической защиты информации LCC-2016 (http://soft.lissi.ru/products/skzi/LCC/) и LirSSL (http://soft.lissi.ru/products/skzi/LCC/):
/*Результаты, полученные в libgcrypt */
GOST=gost512-B 512 bit, testno=8 30ms 900msseckey:
(private-key
(ecc
(curve GOST2012-512-B)
(q #040A4293FF45328CBC6BA41A5F94C612C901FE97A7730E884CC81A701B8D27257DE70B21766BF79E5FAA1E9AE43543C6CF901D910DB5081BBB741F9DD3D9079A5725FDBD2F7A267F88626B5ED0D3EC687389AE01B63207C0C7FD3C86554DB77F21A16FB23327FEE72401087AF1128E662769B6A8F6CE2E27BF8713297CBB41B5A4#)
(d #24ADC433139D97A3E8D5066EFCFD34A9705D4BC932A6FA1B52085B620416AE3772C5C7932C8B4E2666E6D6412F5BA1961F62575CA6058531EB3DA6044DB92D15#)
)
)
data:
(data
(flags gost)
(value #3F05FAFCA2744B46839001314876C4169956F1F3A9A2BFA27A1F55C9EFA74D33CAF6F04EC5AF7591DC16D1BD1B2689C704DD2F2BBE67A7E54987EE08ABC1C213#)
)
sig:
(sig-val
(gost
(r #7977D87E4060D9AF828B146A2A0EF3DFCDC1E35AF32EBAEF5C9364E46C9DB5C2A0159D8DB0E2DAE5C25B17A45454EC73394249DA8FE97951C7F391BB01B5EA5D#)
(s #2EAFC644023E36CADCD0A86D3B9C2EB028AECBA46C89EE27A5081E090A3EAC496091E3A79FBE952019E0EB0925C94A6B6200256F96A1A38AB5E27E066541AC75#)
)
)
/* Результаты тестирования тестовых результатов в LCC-2016 */
Testing id-tc26-gost-3410-2012-512-paramSetB (1.2.643.7.1.2.1.2.2)
Find parameter set by OID OK
Digest:
3F05FAFCA2744B46839001314876C4169956F1F3A9A2BFA27A1F55C9EFA74D33CAF6F04EC5AF7591DC16D1BD1B2689C704DD
2F2BBE67A7E54987EE08ABC1C213
Private key:
24ADC433139D97A3E8D5066EFCFD34A9705D4BC932A6FA1B52085B620416AE3772C5C7932C8B4E2666E6D6412F5BA1961F62
575CA6058531EB3DA6044DB92D15
Private key loaded OK
Public key generated OK
Public key:
x: a4293ff45328cbc6ba41a5f94c612c901fe97a7730e884cc81a701b8d27257de70b21766bf79e5faa1e9ae43543c6cf90
1d910db5081bbb741f9dd3d9079a57
y: 25fdbd2f7a267f88626b5ed0d3ec687389ae01b63207c0c7fd3c86554db77f21a16fb23327fee72401087af1128e66276
9b6a8f6ce2e27bf8713297cbb41b5a4
Loading digest value OK
Signature:
r: 7977D87E4060D9AF828B146A2A0EF3DFCDC1E35AF32EBAEF5C9364E46C9DB5C2A0159D8DB0E2DAE5C25B17A45454EC733
94249DA8FE97951C7F391BB01B5EA5D
s: 2EAFC644023E36CADCD0A86D3B9C2EB028AECBA46C89EE27A5081E090A3EAC496091E3A79FBE952019E0EB0925C94A6B6
200256F96A1A38AB5E27E066541AC75
Signature load OK
Signature verification OK
Но это еще не все. Пришлось вносить изменения и в сам проект gnupg-2, например, в файл sm/sign.c были добавлены oid-ы ГОСТ-хэшей:
switch (cl->hash_algo)
{
case GCRY_MD_SHA1: oid = "1.3.14.3.2.26"; break;
case GCRY_MD_RMD160: oid = "1.3.36.3.2.1"; break;
case GCRY_MD_SHA224: oid = "2.16.840.1.101.3.4.2.4"; break;
case GCRY_MD_SHA256: oid = "2.16.840.1.101.3.4.2.1"; break;
case GCRY_MD_SHA384: oid = "2.16.840.1.101.3.4.2.2"; break;
case GCRY_MD_SHA512: oid = "2.16.840.1.101.3.4.2.3"; break;
/*ORLOV*/
case GCRY_MD_STRIBOG256: /* GOST R 34.11-2012, 256 bit. */
oid = "1.2.643.7.1.1.2.2"; break;
case GCRY_MD_STRIBOG512: /* GOST R 34.11-2012, 512 bit. */
oid = "1.2.643.7.1.1.2.3"; break;
case GCRY_MD_GOSTR3411_94: /* GOST R 34.11-94. */
oid = "1.2.643.7.1.1.2.1"; break;
/* case GCRY_MD_WHIRLPOOL: oid = "No OID yet"; break; */
case GCRY_MD_MD5: /* We don't want to use MD5. */
case 0: /* No algorithm found in cert. */
default: /* Other algorithms. */
log_info (_("hash algorithm %d (%s) for signer %d not supported;"
" using %sn"),
cl->hash_algo, oid? oid: "?", i,
gcry_md_algo_name (GCRY_MD_SHA1));
cl->hash_algo = GCRY_MD_SHA1;
oid = "1.3.14.3.2.26";
break;
}
После внесения всех этих изменений и установки обновленной библиотеки libgcrypt-1.6.5 и утилиты gpgsm был запущен почтовый клиент и прочитано подписанное сообщение. Результат превзошел все наши ожидания:
Теперь осталось разобраться с импортом сертификатов и, самое главное, – ключей. И если с импортом сертификатов все прошло хорошо, то с импортом закрытого ключа из pkcs12 пришлось потрудиться и внести изменения в подпроект agent (модуль gpg-ptotect-tool). Но когда и эти трудности были пройдены, когда были импортированы закрытые ключи (прочитать можно здесь mdf-i.blogspot.ru/2008/10/blog-post_08.html ), пришло время поклониться Клеопатре:
И Клеопатра благосклонно отнеслась к нашим личным (с закрытыми ключами) и не личным сертификатам. Тип сертификата здесь назван «512-битный ЕСС (закрытый ключ доступен)», но это на любителя. На втором снимке прописаны ГОСТ-овые oid-ы (префикс 1.2.643):
Пришло время завершать наше повествование и дать достойный ответ Thunderbird-у российской криптографией. P.S. Убедитесь (это очень важно), что gpg-agent работает:
bash-4.3$ gpg-agent --daemon --use-standard-socket
GPG_AGENT_INFO=/home/a513/.gnupg/S.gpg-agent:6283:1; export GPG_AGENT_INFO;
bash-4.3$
Прежде всего надо выбрать свой личный сертификат (сертификат, у которого есть закрытый ключ), с который вы будете ставить свою ЭП:
Если вы нажмете кнопку «Запустить диспетчер сертификатов», то к вашим услугам будет несравненная Клеопатра! Теперь когда письмо подготовлено, сертификат для ЭП выбран — смело нанажимайте на кнопку/иконку «подписать»:
После этого в теле вашего письма появится, что письмо при отправке будет подписано ЭП. Нажимаем кнопку «отправить»:
Вводим пароль для доступа к закрытому ключу (мы его установили при импорте закрытого ключа) и нажимаем «ОК».
Ну вот и все. Но мы пока ни слова не сказали о шифровании, но это в следующий раз.
Но вопрос все еще остается открытым — а что же дальше?
Автор: