Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline rik  
#1 Оставлено : 29 июля 2014 г. 21:07:19(UTC)
rik

Статус: Новичок

Группы: Участники
Зарегистрирован: 29.07.2014(UTC)
Сообщений: 2
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 1 раз
Дано:
  • Debian 7.4 wheezy
  • КриптоПро CSP 3.6.1


Задачи:

  • Посчитать HMAC на основе известного ключа (в сыром виде) для алгоритма MD5
  • Посчитать HMAC на основе известного ключа (в сыром виде) для алгоритма SHA1
  • Импортировать сырой симметричный ключ ГОСТ 28147-89 для дальнейшего использования
  • Посчитать имитовставку ГОСТ 28147-89, сырой симметричный ключ также прилагается


Подход
Все вышеперечисленные задачи требуют наличия актуального ключа шифрования в понятиях HCRYPTKEY CryptoAPI/CAPILite. В нашем случае, во всех задачах ключ приходит извне в сыром виде, поэтому CryptDeriveKey() и CryptGenKey() неприменимы. Применим, теоретически, CryptImportKey(), описание которого на MSDN (1) содержит отличную ссылку на пример импорта ключа из PLAINTEXTKEYBLOB (2).

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

Практически, код для подобного импорта, c учётом случайных интернетных ссылок (3), выглядит так:
Код:

typedef struct _capi_blob{
  BLOBHEADER header;
  DWORD len;
  BYTE key[];
} capi_blob;
...
void hmac_init(... uint8_t *key, int key_len ...)
  capi_blob *blb;
  DWORD bsize;
...
  bsize = key_len + sizeof(*blb);
  blb = calloc(1, bsize); // who cares about NULL?
  blb->header.bType = PLAINTEXTKEYBLOB;
  blb->header.bVersion = CUR_BLOB_VERSION;
  blb->header.aiKeyAlg = CALG_RC2;
  memcpy(blb->key, key, key_len);
  blb->len = key_len;
  if (!CryptImportKey(cryptoprov, (BYTE *) blb, bsize,
      0, CRYPT_EXPORTABLE, &ctx->c))
    msg("Failed CryptImportKey (0x%x), bsize: 0x%x, key_len: %d", GetLastError(), bsize, key_len);


При этом, cryptoprov может быть получен так:
Код:

...
  if (!CryptAcquireContext(
                           &cryptoprov,
                           0,
                           NULL,
                           PROV_GOST_2001_DH,
                           CRYPT_VERIFYCONTEXT))
...


А может быть так:
Код:

...
  if (!CryptAcquireContext(cprov, "TestContainer", MS_ENHANCED_PROV,
                           PROV_RSA_FULL, CRYPT_NEWKEYSET))
...

Что имеет своё влияние на результат, но об этом ниже.

Проблема
При использовании указанного выше подхода для самой первой задачи имеем с провайдером PROV_GOST_2001_DH:

Код:
Failed CryptImportKey (0x80090005), bsize: 0x24, key_len: 24


При использовании PROV_RSA_FULL:

Код:
Failed CryptImportKey (0x57), bsize: 0x24, key_len: 24


Очевидно, что ни NTE_BAD_DATA, ни ERROR_INVALID_PARAMETER не являются корректными ответами на поставленную задачу. В связи с чем были проведёны дополнительные исследования вопроса.

Дополнительне подходы
Во-первых, было подозрение на размер ключа и связь с CRYPT_IPSEC_HMAC_KEY, но, увы, как показало ручное обрезание ключа до 16, 8 и 5 байт, результат не меняется.

Во-вторых, коль скоро наш ключ на входе имеет длину в 24 байта или 192 бита, была произведена замена CALG_RC2 на CALG_3DES, результат не изменился.

В-третьих, был опробован существенно более сложный путь импорта через PRIVATEKEYBLOB (4), код этого варианта на 95% соответствует четвёртой ссылке, но и он результата не дал, ошибки те же.

В-четвёртых, так как, теоретически, реализации разных RC2/RC4/3DES и прочей ереси в библиотеках "КриптоПро" может и не быть (хотя в заголовках-то всё есть), был опробован импорт CALG_G28147 с размером ключа в 32 байта как по схеме PLAINTEXTKEYBLOB, так и по схеме PRIVATEKEYBLOB, что уже имеет прямое отношение к третьей и четвёртой задачам. Результат стабильный и неизменный --- те же ошибки, с поправкой на криптопровайдера.

Вопросы
1) Как же нам посчитать HMAC, может есть другие методы?
2) Как заимпортировать сырой ключ ГОСТ 28147-89?
3) Что случилось с CRYPT_IPSEC_HMAC_KEY?

Ссылки
1) http://msdn.microsoft.co...p/aa380207(v=vs.85).aspx
2) http://msdn.microsoft.co...p/aa382383(v=vs.85).aspx
3) http://masm32.com/board/index.php?topic=1612.0
4) http://www.phdcc.com/cryptorc4.htm
Offline rik  
#2 Оставлено : 30 июля 2014 г. 19:52:53(UTC)
rik

Статус: Новичок

Группы: Участники
Зарегистрирован: 29.07.2014(UTC)
Сообщений: 2
Российская Федерация
Откуда: Санкт-Петербург

Сказал(а) «Спасибо»: 1 раз
По итогу разбирательств:

  • импорт через PLAINTEXTKEYBLOB с провайдером "Крипто-Про" не работает ни под линуксами, ни под виндой
  • под линуксами провайдер MS_ENHANCED_PROV/PROV_RSA_FULL принципиально неработоспособен (что не было замечено ранее), что жаль, ибо при его использовании под виндой ключ RC2 через PLAINTEXTKEYBLOB для HMAC работает на ура, в MSDN не врут
  • импорт через PRIVATEKEYBLOB и ключ RSA с экспонентой 1 не работает
  • работает импорт ключа ГОСТ 28147-89 через шифрованный SIMPLEBLOB, описанный в теме https://www.cryptopro.ru....aspx?g=posts&t=2939 , спасибо ув. тов. amdei
  • работает он, однако, только для ГОСТовых ключей правильного размера, поэтому для подсчёта HMAC с длинами ключей отличающимися от 32 необходимо брать в руки RFC 2104 и писать реализацию с использованием простых хэшей
  • в свете вышеизложенного, CRYPT_IPSEC_HMAC_KEY, действительно, не имеет смысла под линуксами и поэтому-то и не определён

Отредактировано пользователем 30 июля 2014 г. 19:54:48(UTC)  | Причина: Не указана

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.