Более двух лет прошло после выхода первого релиза библиотеки 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/) было отправлено подписанное сообщение:

image

К сожалению, почтовый клиент KMail, получив это сообщение, не смог проверить ЭП:

image

Клеопатра также отказывалась признавать российские сертификаты. Мы приступили к анализу ситуации. Естественно, начали с библиотеки 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 %s\n"),
                    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 был запущен почтовый клиент и прочитано подписанное сообщение. Результат превзошел все наши ожидания:

image

Теперь осталось разобраться с импортом сертификатов и, самое главное, – ключей. И если с импортом сертификатов все прошло хорошо, то с импортом закрытого ключа из pkcs12 пришлось потрудиться и внести изменения в подпроект agent (модуль gpg-ptotect-tool). Но когда и эти трудности были пройдены, когда были импортированы закрытые ключи (прочитать можно здесь mdf-i.blogspot.ru/2008/10/blog-post_08.html ), пришло время поклониться Клеопатре:

image

И Клеопатра благосклонно отнеслась к нашим личным (с закрытыми ключами) и не личным сертификатам. Тип сертификата здесь назван «512-битный ЕСС (закрытый ключ доступен)», но это на любителя. На втором снимке прописаны ГОСТ-овые oid-ы (префикс 1.2.643):

image

Пришло время завершать наше повествование и дать достойный ответ 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$

Прежде всего надо выбрать свой личный сертификат (сертификат, у которого есть закрытый ключ), с который вы будете ставить свою ЭП:

image

Если вы нажмете кнопку «Запустить диспетчер сертификатов», то к вашим услугам будет несравненная Клеопатра! Теперь когда письмо подготовлено, сертификат для ЭП выбран — смело нанажимайте на кнопку/иконку «подписать»:

image

После этого в теле вашего письма появится, что письмо при отправке будет подписано ЭП. Нажимаем кнопку «отправить»:

image

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

Но вопрос все еще остается открытым — а что же дальше?

Комментарии (9)


  1. miga
    07.04.2016 12:55
    +3

    И про катастрофу с кодировками тоже расскажите :)


    1. a513
      13.04.2016 10:42

      Это не катастрофа…


  1. lumag
    07.04.2016 15:58

    Про кривые — очень странно. В январе 2014 добавили поддержку кривых по ГОСТ 34.10-2001 и ГОСТ 34.10-2012. Какую версию libgcrypt Вы используете?


    1. a513
      13.04.2016 10:33

      Спасибо.
      Версия, как указано в статье, 1.6.5.
      Да в январе добавлена поддержку кривых по ГОСТ 34.10-2001 и ГОСТ 34.10-2012, но только с тестовыми параметрами алгоритма подписи ГОСТ Р 34.10-2001 и тестовыми параметрами алгоритма подписи ГОСТ Р 34.10-2012 с ключом 512. Именно об этом и идет речь.


      1. lumag
        13.04.2016 19:10

        Да, я уже увидел, что коммиты (на которые я дал ссылки) с поддержкой кривых попали в HEAD, но не в ветку 1.6.x.
        Кстати говоря, в HEAD также частично переделана поддержка ГОСТ 28147-89.


        1. a513
          14.04.2016 08:25

          Спасибо, нашел.


  1. lumag
    07.04.2016 16:20

    Из интересных моментов, было бы интересно посмотреть на патчи для libksba.


    1. a513
      13.04.2016 10:41

      Да, вы правильно заметили, дорабатывать пришлось и libksba (keyinfo.c).


  1. dartraiden
    07.04.2016 17:50
    +1

    А что насчёт отправки патчей в апстрим? Или хотя бы исходников? На вашем сайте я нашёл лишь готовые бинарники (тут и тут), а такой хоккей нам не нужен…