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

Уведомление

Icon
Error

3 Страницы<123>
Опции
К последнему сообщению К первому непрочитанному
Offline Роман кислухин  
#11 Оставлено : 16 августа 2013 г. 12:52:08(UTC)
Роман кислухин

Статус: Активный участник

Группы: Участники
Зарегистрирован: 29.03.2011(UTC)
Сообщений: 163
Мужчина
Откуда: Москва

Сказал «Спасибо»: 8 раз
Поблагодарили: 3 раз в 3 постах
Итак. Получен кусок неработающего кода. Приведу его как есть на Java, чтобы не ошибиться при транслировании на Си. Он в принципе понятен.

Шифрование проходит без проблем:
Код:

  public static CryptData cryptData(PCCERT_CONTEXT cert, byte[] data) throws CryptoException {
    final KeyContext userKey = SignUtils.getUserKey(cert);
    if (userKey == null)
      throw new CryptoException("User key not found");
    final Pointer sessKey = Advapi.cryptGenKey(userKey.getProvHandle(), Wincrypt.CALG_G28147, Wincrypt.CRYPT_EXPORTABLE);
    try {
      final byte[] ecnryptedData = Advapi.cryptEncrypt(sessKey, null, true, data);
      final byte[] iv = new byte[8];
      final byte[] sv = new byte[8];
      final byte[] sessKeyData = exportSessionKey(userKey, sessKey, iv, sv);
      return new CryptData(ecnryptedData, sessKeyData, iv, sv);
    } finally {
      userKey.free();
    }
  }

  private static byte[] exportSessionKey(KeyContext userKey, Pointer sessionKey, /* out */ byte[] iv, /* out */ byte[] sv) throws CryptoException {
    final Pointer hProv = userKey.getProvHandle();
    // получаем вектор инициализации
    final byte[] ivData = cryptGetKeyParam(sessionKey, KP_IV);
    // копируем вектор в out - переменную
    System.arraycopy(ivData, 0, iv, 0, 8);

    // генерируем ефемерную пару
    final Pointer ephemKey = Advapi.cryptGenKey(hProv, CALG_DH_EL_EPHEM, CRYPT_EXPORTABLE);

    // Генерируем в 2 шага ключ согласования agreeKey. Для этого импортируем наш публичный ключ, используя эфемерную пару.
    // 1. Экспортируем наш публичный ключ
    final byte[] pubKeyData = cryptExportKey(userKey.getKeyHandle(), null, PUBLICKEYBLOB, 0);
    // 2. Импортируем при помощи эфемерной пары
    final Pointer agreeKey = Advapi.cryptImportKey(hProv, pubKeyData, ephemKey, 0);

    // получаем вектор инициализации
    final byte[] svData = cryptGetKeyParam(agreeKey, KP_IV);
    // копируем вектор в out - переменную
    System.arraycopy(svData, 0, sv, 0, 8);

    // Экспортируем симметричный ключ шифрования с использованием ключа согласования
    final byte[] sessKeyData = cryptExportKey(sessionKey, agreeKey, SIMPLEBLOB, 0);

    return sessKeyData;
  }

В результате получаем зашифрованный симметричный сессионный ключ и два вектора инициализации.
А вот с расшифровкой проблемы:

Код:

  public static byte[] decryptData(PCCERT_CONTEXT cert, CryptData cdata) throws CryptoException {
    final KeyContext userKey = SignUtils.getUserKey(cert);
    if (userKey == null)
      throw new CryptoException("User key not found");
    final Pointer sessKey = importSessionKey(userKey, cdata);
    try {
      final byte[] data = Advapi.cryptDecrypt(sessKey, null, true, 0, cdata.cryptedData);
      return data;
    } finally {
      userKey.free();
    }
  }

  private static Pointer importSessionKey(KeyContext userKey, CryptData cdata) throws CryptoException {
    final Pointer hProv = userKey.getProvHandle();
    // генерируем ефемерную пару
    final Pointer ephemKey = Advapi.cryptGenKey(hProv, CALG_DH_EL_EPHEM, CRYPT_EXPORTABLE);

    // Генерируем в 2 шага ключ согласования agreeKey. Для этого импортируем эфемерный открытый ключ, используя нашу ключевую пару.
    // 1. Экспортируем эфемерный публичный ключ
    final byte[] ephemPubKeyData = cryptExportKey(ephemKey, null, PUBLICKEYBLOB, 0);
    // 2. Импортируем при помощи ключевой пары
    final Pointer agreeKey = Advapi.cryptImportKey(hProv, ephemPubKeyData, userKey.getKeyHandle(), 0);

    // устанавливаем вектор инициализации
    cryptSetKeyParam(agreeKey, KP_IV, cdata.sv, 0);

    // Импортируем симметричный ключ шифрования с использованием ключа согласования
    final Pointer sessKey = cryptImportKey(hProv, cdata.ecnryptedKey, agreeKey, 0);
    if (sessKey == null) 
      throw CryptoUtil.raiseCryptoError("cryptImportKey", getLastError()); // ОШИБКА ЗДЕСЬ. Bad data (0x80090005)

    // Не забываем вектор инициализации
    final byte[] ivData = cdata.iv;
    cryptSetKeyParam(sessKey, KP_IV, ivData, 0);

    return sessKey;
  }

Возникает ошибка на этапе импорта сессионного ключа - Bad data (0x80090005).

Что пропустил? Подвох в эфемерном ключе? Надо передавать его значение вместе со всеми данными? Или еще где ошибся?

отступы почему-то пропали :(

Отредактировано пользователем 16 августа 2013 г. 12:58:47(UTC)  | Причина: Не указана

Offline Роман кислухин  
#12 Оставлено : 16 августа 2013 г. 14:01:16(UTC)
Роман кислухин

Статус: Активный участник

Группы: Участники
Зарегистрирован: 29.03.2011(UTC)
Сообщений: 163
Мужчина
Откуда: Москва

Сказал «Спасибо»: 8 раз
Поблагодарили: 3 раз в 3 постах
Так, с двумя ключевыми парами пример заработал. Значит дело в эфемерном ключе. Попробую CRYPT_PREGEN - где-то видел в примерах.
Offline Максим Коллегин  
#13 Оставлено : 16 августа 2013 г. 14:04:01(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
cryptGenKey(hProv, CALG_DH_EL_EPHEM, CRYPT_EXPORTABLE); при экспорте и импорте - это что-то странное. Передавайте открытый ключ эферного ключа на сторону расшифрования.
Знания в базе знаний, поддержка в техподдержке
Offline Роман кислухин  
#14 Оставлено : 16 августа 2013 г. 14:25:05(UTC)
Роман кислухин

Статус: Активный участник

Группы: Участники
Зарегистрирован: 29.03.2011(UTC)
Сообщений: 163
Мужчина
Откуда: Москва

Сказал «Спасибо»: 8 раз
Поблагодарили: 3 раз в 3 постах
Автор: maxdm Перейти к цитате
cryptGenKey(hProv, CALG_DH_EL_EPHEM, CRYPT_EXPORTABLE); при экспорте и импорте - это что-то странное. Передавайте открытый ключ эферного ключа на сторону расшифрования.


Согласен. Сейчас попробую целиком его экспортнуть.
Offline Роман кислухин  
#15 Оставлено : 16 августа 2013 г. 14:33:51(UTC)
Роман кислухин

Статус: Активный участник

Группы: Участники
Зарегистрирован: 29.03.2011(UTC)
Сообщений: 163
Мужчина
Откуда: Москва

Сказал «Спасибо»: 8 раз
Поблагодарили: 3 раз в 3 постах
Не помогло. Что-то еще не так.

делаю так:
Код:

    // экспортируем эфемерный ключ. Он нам понадобится для расшифрования.
    cdata.pubKeyData = cryptExportKey(ephemKey, null, PUBLICKEYBLOB, 0);

    // получаем вектор инициализации
    cdata.sv = cryptGetKeyParam(agreeKey, KP_IV);

    // Экспортируем симметричный ключ шифрования с использованием ключа согласования
    cdata.ecnryptedKey = cryptExportKey(sessionKey, agreeKey, SIMPLEBLOB, 0);


потом
Код:

    // Импортируем при помощи ключевой пары
    final Pointer agreeKey = cryptImportKey(hProv, cdata.pubKeyData, userKey.getKeyHandle(), 0);

    // устанавливаем вектор инициализации
    cryptSetKeyParam(agreeKey, KP_IV, cdata.sv, 0);

    // Импортируем симметричный ключ шифрования с использованием ключа согласования
    final Pointer sessKey = cryptImportKey(hProv, cdata.ecnryptedKey, agreeKey, 0);


И все равно Bad data.
Offline Максим Коллегин  
#16 Оставлено : 16 августа 2013 г. 14:53:46(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
хм, вектор инициализации нужно ставить сессионному ключу. Вы наши примеры из SDK смотрели? Зачем гадать?
Знания в базе знаний, поддержка в техподдержке
Offline Роман кислухин  
#17 Оставлено : 16 августа 2013 г. 14:59:56(UTC)
Роман кислухин

Статус: Активный участник

Группы: Участники
Зарегистрирован: 29.03.2011(UTC)
Сообщений: 163
Мужчина
Откуда: Москва

Сказал «Спасибо»: 8 раз
Поблагодарили: 3 раз в 3 постах
Автор: maxdm Перейти к цитате
хм, вектор инициализации нужно ставить сессионному ключу. Вы наши примеры из SDK смотрели? Зачем гадать?


Ему я тоже ставлю, но до этого не доходит.
Самое интересное, что этот же код работает при наличии двух ключевых пар. А вот с эфемерной - не работает.
Если убрать установку вектора инициализации для ключа согласования, все равно выдает Bad data.

p.s. не стало работать :( разбираюсь. Судя по всему, причина в неаккуратном использовании хэндлов на провайдер. Сколько их должно быть для всех операций шифрования/дешифрования?

Отредактировано пользователем 16 августа 2013 г. 15:08:38(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#18 Оставлено : 16 августа 2013 г. 15:11:02(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
Мда.
При шифровании вообще ерунда какая-то. Зачем вы импортируете открытый эферный ключ в закрытый. Закрытый ключ отправителя в этой схеме вообще не нужен.
Знания в базе знаний, поддержка в техподдержке
Offline Максим Коллегин  
#19 Оставлено : 16 августа 2013 г. 15:11:25(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
Еще раз повторяю - посмотрите примеры.
Знания в базе знаний, поддержка в техподдержке
Offline Роман кислухин  
#20 Оставлено : 16 августа 2013 г. 15:19:54(UTC)
Роман кислухин

Статус: Активный участник

Группы: Участники
Зарегистрирован: 29.03.2011(UTC)
Сообщений: 163
Мужчина
Откуда: Москва

Сказал «Спасибо»: 8 раз
Поблагодарили: 3 раз в 3 постах
Автор: maxdm Перейти к цитате
Еще раз повторяю - посмотрите примеры.


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

смотрю сюда:
http://cpdn.cryptopro.ru...ngSessionKeyExample.html
в этой схеме используются оба ключа, и импорт публичного ключа получателя делается с ключевой парой отправителя. С эфемерной не так?

Отредактировано пользователем 16 августа 2013 г. 15:29:49(UTC)  | Причина: Не указана

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