Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> CryptoAPI RSA шифрование 
:(
    Опции темы
tofreesky
Дата 9.2.2012, 20:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 152
Регистрация: 9.6.2010

Репутация: нет
Всего: нет



Вы вопроса не видите что ли? Все что вы говорите понятно, но так где в вашем коде приватный ключ? Одним и тем же расшифровывается. 
PM MAIL   Вверх
feodorv
Дата 9.2.2012, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(tofreesky @  9.2.2012,  20:46 Найти цитируемый пост)
Вы вопроса не видите что ли?

Гм. По-моему, так это Вы ответа не видите. А ещё говорите понятный код((((

Цитата(tofreesky @  9.2.2012,  20:46 Найти цитируемый пост)
где в вашем коде приватный ключ?

Код не мой. А приватный ключ получаем через вызов CryptGetUserKey.

Добавлено через 42 секунды
Им расшифровывается сессионный ключ.

Добавлено через 5 минут и 3 секунды
То, что Вы нагородили с "key_pub.rsa" и "key_prv.rsa" - совершенно неверно, так как в случае дешифровки публичный ключ нужен только для проверки подписи.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
tofreesky
Дата 9.2.2012, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 152
Регистрация: 9.6.2010

Репутация: нет
Всего: нет



Там мне нужно одним ключом(публичным) шифровать, а приватным расшифровывать. Обычная схема. Только в вашем(моем) коде используется один ключ для всего. А мне нужно два отдельных.
PM MAIL   Вверх
feodorv
Дата 9.2.2012, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(tofreesky @  9.2.2012,  21:54 Найти цитируемый пост)
Только в вашем(моем) коде используется один ключ для всего

Да нет же. Используются и открытый, и приватный ключи.

Цитата(tofreesky @  9.2.2012,  21:54 Найти цитируемый пост)
мне нужно одним ключом(публичным) шифровать, а приватным расшифровывать.

Так не делают. 


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
tofreesky
Дата 9.2.2012, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 152
Регистрация: 9.6.2010

Репутация: нет
Всего: нет



Цитата

Да нет же. Используются и открытый, и приватный ключи.


Где же? Видно что экспортируется публичный ключ.

Цитата

Так не делают.  


Лол. А как делают? Извините, но, вы вообще о асимметричной криптографии не слышали походу....

Добавлено через 2 минуты и 15 секунд
Ассиметричное шифрование (криптография с открытым ключом) - асимметричная схема, в которой применяются пары ключей: открытый ключ (public key), который зашифровывает данные, и соответствующий ему закрытый ключ (private key), который их расшифровывает. Открытый ключ можно распространить хоть по всему миру, в то время как закрытый держится в тайне. Любой человек с копией открытого ключа может зашифровать информацию, которую сможет прочитать только владелец закрытого ключа. Кто угодно. Даже люди, с которыми вы прежде никогда не встречались.
PM MAIL   Вверх
feodorv
Дата 9.2.2012, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(tofreesky @  9.2.2012,  22:23 Найти цитируемый пост)
А как делают? Извините, но, вы вообще о асимметричной криптографии не слышали походу....

Так можно, но так не делают:
Цитата

Ассиметричные алгоритмы в обычной жизни мало применимы. Причина тому – высокая трудоемкость шифрования, обусловленная повышенной сложностью ассиметричных алгоритмов. Обычно используют следующую схему: шифрование данных выполняется симметричным криптографическим алгоритмом некоторым сгенерированным для этого сессионным ключом. Затем для передачи получателю этот ключ шифруется с помощью асимметричного алгоритма (длина ключа несущественно мала по сравнению с возможным размером данных). На стороне получателя с помощью асимметричного алгоритма расшифровывается сессионный ключ, который используется для расшифровывания полученных данных с помощью симметричного алгоритма. Такой способ передачи шифрованной информации позволяет использовать преимущества обоих подходов.

Именно такой подход использован во всех ключевых алгоритмах работы Crypto API. Контейнеры ключей хранят пары ключей, необходимые для обмена сессионными ключами, а для непосредственно шифрования данных необходимо каждый раз генерировать новые сессионные ключи.

Использование Crypto API
Цитата(tofreesky @  9.2.2012,  22:23 Найти цитируемый пост)
Ассиметричное шифрование (криптография с открытым ключом) - асимметричная схема, в которой применяются пары ключей: открытый ключ (public key), который зашифровывает данные, и соответствующий ему закрытый ключ (private key), который их расшифровывает. Открытый ключ можно распространить хоть по всему миру, в то время как закрытый держится в тайне. Любой человек с копией открытого ключа может зашифровать информацию, которую сможет прочитать только владелец закрытого ключа. Кто угодно. Даже люди, с которыми вы прежде никогда не встречались. 

Поражён Вашими знаниями  smile 


Цитата(tofreesky @  9.2.2012,  22:23 Найти цитируемый пост)
Где же? Видно что экспортируется публичный ключ.

Мдя. 

Экспортируется публичный ключ "для обмена". Это значит, что Вы можете файл с незашифрованным публичным ключом перенести на другую инсталляцияю ОС и с помощью него зашифровывать данные, которые может расшифровать только владелец приватного ключа. Но не "им зашифровывать", а "с помощью него зашифровывать", так как схема более изощрённая. Экспорт приватного ключа для расшифровки данных не имеет смысла.

Схема зашифровки файла:
  • получаем открытый ключ; в коде через CryptImportKey(hProv,(BYTE *)&key,sizeof(RSAPubKey1024),NULL,0,&hPubKey)
  • генерируем сессионный ключ CryptGenKey(hProv,CALG_3DES,CRYPT_EXPORTABLE,&hKey)
  • зашифровываем сессионный ключ CryptExportKey(hKey,hPubKey,SIMPLEBLOB,0,(BYTE *)&fh.kb,&dwLen) с помощью открытого ключа и сбрасываем его в выходной файл
  • шифруем содержимое файла CryptEncrypt(hKey,hHash,fSize<=BUFFER_SIZE,0,buf,&dwSzLow,sizeof(buf)) и сбрасываем в выходной файл
  • генерируем подпись CryptSignHash(hHash,AT_SIGNATURE,NULL,0,buf,&dwLen) и сбрасываем в выходной файл
Как видно, в схеме зашифровки участвует открытый ключ как для шифрования сессионного ключа, так и для получения подписи.

Схема расшифровки файла:
  • получаем закрытый ключ CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hPrivKey) (в реальности, получаем целую пару AT_KEYEXCHANGE ключей, но в CryptImportKey будет участвовать именно закрытый ключ)
  • считываем зашифрованный сессионный ключ и расшифровываем его CryptImportKey(hProv,(BYTE *)&fh.kb,sizeof(RSA1024KeyExchBLOB),hPrivKey,0,&hKey)
  • сессионным ключом расшифровываем содержимое файла и сбрасываем расшифрованное содержимое в выходной файл
  • проверяем подпись CryptVerifySignature(hHash,buf,1024/8,hPubKey,NULL,0) открытым ключом.
Как видно, в схеме расшифровки участвует закрытый ключ.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
tofreesky
Дата 9.2.2012, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 152
Регистрация: 9.6.2010

Репутация: нет
Всего: нет



Цитата

получаем закрытый ключ CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hPrivKey)


Откуда его берут?
PM MAIL   Вверх
feodorv
Дата 10.2.2012, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(tofreesky @  9.2.2012,  23:09 Найти цитируемый пост)
Откуда его берут? 

Как откуда??? Из локального контейнера ключей! Как Вы думаете, что кроме всего делает функция CryptAcquireContext?

Код

 if( !CryptAcquireContext( &hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL, 0) && 
     !CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL, CRYPT_NEWKEYSET) ) //пытаемся открыть существующий keyset или создать новый

Если контейнера ключей с именем, совпадающим с именем текущего пользователя (второй аргумент функции - NULL), не существует, то создадим его (на что указывает флаг CRYPT_NEWKEYSET). Если задать флаг CRYPT_DELETEKEYSET, то можно удалить этот контейнер.

Именно в этом контейнере хранятся пары открытый/закрытый ключ (AT_KEYEXCHANGE или AT_SIGNATURE).


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 10.2.2012, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Не поленился воспользоваться советом volatile
Цитата(volatile @  9.2.2012,  00:03 Найти цитируемый пост)
поробуйте разбить функцию на несколько штук, вменяемого размера.

Ну и немного изменил код, убив всякое упоминание о "key.rsa".

Генерация ключей
Код

#include <Windows.h>
#include <WinCrypt.h>
#include <stdio.h>

#pragma comment (lib, "advapi32.lib")

BOOL GenerateKey()
{
  HCRYPTPROV hProv;
  HCRYPTKEY hKey;
  BOOL success = TRUE;

  if( !CryptAcquireContext( &hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0) &&
      !CryptAcquireContext( &hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) ) //пытаемся открыть существующий keyset или создать новый
  {
    printf( "Не удается создать контекст\n" );
    return FALSE;
  }

  if( !CryptGenKey( hProv, AT_KEYEXCHANGE, 1024<<16, &hKey) ) //генерируем 1024-битный ключ для обмена
  {
    printf( "Не удается создать ключ RSA для обмена\n" );
    success = FALSE;
  }

  CryptReleaseContext( hProv, 0);
  if( success ) printf( "Успешно создан ключ RSA для обмена\n" );

  return success;
}

int main( void )
{
  return GenerateKey() ? 0 : -1;
}


Шифрование файла
Код

#include <Windows.h>
#include <WinCrypt.h>
#include "utils.h"
#include <stdio.h>

#pragma comment (lib, "advapi32.lib")

BOOL _EncryptFile( char *_InFile, char *_OutFile)
{
  HCRYPTPROV hProv;
  HCRYPTKEY hPubKey;
  HCRYPTHASH hHash;
  HANDLE hInFile = INVALID_HANDLE_VALUE, hOutFile = INVALID_HANDLE_VALUE;
  BOOL success = TRUE;

  if( !CryptAcquireContext( &hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0) ) //получаем контекст
  {
    printf( "Не удается получить контекст\n" );
    return FALSE;
  }

  if( !CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hPubKey) ) //достаем публичный ключ пользователя
  {
    puts( "Не удается получить публичный ключ из контейнера\n" );
    CryptReleaseContext( hProv, 0);
    return FALSE;
  }

  if( (hInFile = CreateFileA( _InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE ) //открываем входной файл
  {
    printf( "Не удается открыть входной файл\n" );
    success = FALSE;
  }

  if( success && (hOutFile = CreateFileA( _OutFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE ) //открываем выходной файл
  {
    printf("Не удается открыть выходной файл\n");
    success = FALSE;
  }

  if( success ) if( CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash) ) //создаем хэш
  {
    HCRYPTKEY hKey;

    if( CryptGenKey( hProv, CALG_3DES, CRYPT_EXPORTABLE, &hKey) ) //генерируем ключ для 3DES
    {
      EncFileHeader fh;
      DWORD dwLen = sizeof(struct RSA1024KeyExchBLOB);

      if( CryptExportKey( hKey, hPubKey, SIMPLEBLOB, 0, (BYTE *) &fh.kb, &dwLen) ) //экспортируем ключ 3DES
      {
        DWORD dwSzHigh, dwSzLow = GetFileSize( hInFile, &dwSzHigh); //получаем размер исходного файла
        unsigned __int64 fSize = (dwSzHigh << 32) + dwSzLow;
        BYTE buf[BUFFER_SIZE+8]; //8 - запас на padding

        fh.fSize = fSize;

        if( WriteFile( hOutFile, &fh, sizeof(EncFileHeader), &dwLen, NULL) ) //пишем ключ и размер исходного файла
        {
          while( fSize )
          {
            if( !ReadFile( hInFile, buf, BUFFER_SIZE, &dwLen, NULL) ) //читаем блок данных
            {
              printf( "Ошибка чтения файла\n" );
              success = FALSE;
              break;
            }
            dwSzLow = dwLen;
            if( !CryptEncrypt( hKey, hHash, fSize <= BUFFER_SIZE, 0, buf, &dwSzLow, sizeof(buf)) ) //шифруем и хешируем его
            {
              printf( "Ошибка шифрования\n" );
              success = FALSE;
              break;
            }
            if( !WriteFile( hOutFile, buf, dwSzLow, &dwSzLow, NULL) )
            {
              printf( "Ошибка записи\n" );
              success = FALSE;
              break;
            }
            fSize -= dwLen;
          }
          if( !fSize ) //все зашифровали нормально
          {
            dwLen = sizeof(buf);
            if( CryptSignHash( hHash, AT_KEYEXCHANGE, NULL, 0, buf, &dwLen) ) //подписываем хэш
            {
              if( !WriteFile( hOutFile, buf, dwLen, &dwLen, NULL) )
                printf( "Ошибка записи хеша в файл\n" );
              else
                printf( "Шифрование успешно завершено\n" );
            }
            else
              printf( "Не удается подписать файл\n" );
          }
        }
        else
          printf( "Не удается сохранить ключ 3DES\n" );
      }
      else
        printf( "Не удается экспортировать ключ 3DES\n" );
      CryptDestroyKey( hKey );
      CryptDestroyHash( hHash );
    }
    else
      printf( "Не удается создать ключ 3DES\n" );
  }
  else
    puts( "Не удается создать хэш\n" );

  if( hOutFile != INVALID_HANDLE_VALUE ) CloseHandle( hOutFile );
  if( hInFile != INVALID_HANDLE_VALUE ) CloseHandle( hInFile );
  CryptDestroyKey( hPubKey );
  CryptReleaseContext( hProv, 0);
  return success;
}

int main()
{
  return _EncryptFile( "in.bin", "out.bin") ? 0 : -1;
}


Дешифрование файла
Код

#include <Windows.h>
#include <WinCrypt.h>
#include "utils.h"
#include <stdio.h>

#pragma comment (lib, "advapi32.lib")

BOOL _DecryptFile( char *_InFile, char *_OutFile)
{
  HCRYPTPROV hProv;
  HCRYPTKEY hPrivKey;
  HCRYPTHASH hHash;
  HANDLE hInFile = INVALID_HANDLE_VALUE, hOutFile = INVALID_HANDLE_VALUE;
  BOOL success = TRUE;

  if( !CryptAcquireContext( &hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0) ) //получаем контекст
  {
    printf( "Не удается получить контекст\n" );
    return FALSE;
  }

  if( !CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hPrivKey) ) //достаем приватный ключ пользователя
  {
    printf( "Не удается получить приватный ключ из контейнера\n" );
    CryptReleaseContext( hProv, 0);
    return FALSE;
  }

  if( (hInFile = CreateFileA( _InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE ) //открываем входной файл
  {
    printf( "Не удается открыть входной файл\n" );
    success = FALSE;
  }

  if( success && (hOutFile = CreateFileA( _OutFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE ) //открываем выходной файл
  {
    printf("Не удается открыть выходной файл\n");
    success = FALSE;
  }

  if( success ) if( CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash) ) //создаем хэш
  {
    EncFileHeader fh;
    DWORD dwLen;

    if( !ReadFile( hInFile, &fh, sizeof(fh), &dwLen, NULL) )
    {
      printf( "Ошибка чтения файла\n");
      success = FALSE;
    }
    else
    {
      HCRYPTKEY hKey;

      if( CryptImportKey( hProv, (BYTE *) &fh.kb, sizeof(struct RSA1024KeyExchBLOB), hPrivKey, 0, &hKey) ) //импортируем сессионный ключ
      {
        unsigned __int64 fOrgSize = fh.fSize, fEncSize;
        DWORD dwSzLow, dwSzHigh;
        BYTE buf[BUFFER_SIZE];
        dwSzLow = GetFileSize( hInFile, &dwSzHigh);
        fEncSize = (dwSzHigh << 32) + dwSzLow - sizeof(EncFileHeader) - 1024/8; //размер зашифрованных данных

        while( fEncSize )
        {
          if( !ReadFile( hInFile, buf, fEncSize >= BUFFER_SIZE ? BUFFER_SIZE : (DWORD)fEncSize, &dwLen, NULL) )
          {
            printf( "Ошибка чтения\n" );
            success = FALSE;
            break;
          }
          dwSzLow = dwLen;
          if( !CryptDecrypt( hKey, hHash, fEncSize <= BUFFER_SIZE, 0, buf, &dwSzLow) ) //расшифровываем данные
          {
            printf( "Ошибка дешифрования\n" );
            success = FALSE;
            break;
          }
          if( !WriteFile( hOutFile, buf, fOrgSize >= dwSzLow ? dwSzLow : (DWORD) fOrgSize, &dwSzLow, NULL) )
          {
            printf( "Ошибка записи\n" );
            success = FALSE;
            break;
          }
          fEncSize -= dwLen;
          fOrgSize -= dwSzLow;
        }

        if( !fEncSize ) //все нормально отработалось
        {
          if( ReadFile( hInFile, buf, 1024/8, &dwLen, NULL) && dwLen == 1024/8 ) //читаем подпись
          {
            if( !CryptVerifySignature( hHash, buf, 1024/8, hPrivKey, NULL, 0) )
            {
              success = FALSE;
              printf( "Ошибка проверки подписи. Возможно файл был поврежден\n" );
            }
            else
              printf( "Файл успешно расшифрован\n" );
          }
          else
          {
            printf( "Не найдена сигнатура файла\n" );
            success = FALSE;
          }
        }
        CryptDestroyKey( hKey );
      }
      else
      {
        printf( "Не удается импортировать ключ шифрования\n" );
        success = FALSE;
      }
      CryptDestroyKey( hPrivKey );
    }
    CryptDestroyHash(hHash);
  }

  if( hOutFile != INVALID_HANDLE_VALUE ) CloseHandle( hOutFile );
  if( hInFile != INVALID_HANDLE_VALUE ) CloseHandle( hInFile );
  CryptDestroyKey( hPrivKey );
  CryptReleaseContext( hProv, 0);
  return success;
}

int main()
{
  return _DecryptFile( "out.bin", "out_b.bin") ? 0 : -1;
}


Заголовочный файл utils.h
Код

#ifndef _UTILS_H_
#define _UTILS_H_

struct RSA1024KeyExchBLOB
{
  PUBLICKEYSTRUC publickeystruc;
  ALG_ID algid;
  BYTE encryptedkey[1024/8];
};

#define BUFFER_SIZE (1<<14)

typedef struct
{
  struct RSA1024KeyExchBLOB kb;
  unsigned __int64 fSize;
} EncFileHeader;

#endif


Код рабочий, хотя я и мог где-нибудь напортачить)))
Как видно, при шифровании и дешифровании файла вызывается одна и та же функция CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hPubKey или &hPrivKey), в реальности возвращающая сразу пару ключей. В зависимости от функции используется либо открытый, либо закрытый ключ. В MS-коде просто подчеркнули использование публичного ключа для шифрования, чтобы не было никаких сомнений, а вот использование приватного ключа не столь очевидно. smile 

Это сообщение отредактировал(а) feodorv - 10.2.2012, 00:58


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
xvr
Дата 10.2.2012, 09:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(tofreesky @ 9.2.2012,  23:09)
Цитата

получаем закрытый ключ CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hPrivKey)


Откуда его берут?

Так, сугубо для уточнения - этой программой (и с закрытым ключем) вы сможете расшифровать файл только на той машине, где его шифровали. Если же вам нужно расшифровывать его на другой машине, то туда нужно будет перенести этот самый KEYSET (или сменить способ шифрования и обмена ключами)

PM MAIL   Вверх
tofreesky
Дата 10.2.2012, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 152
Регистрация: 9.6.2010

Репутация: нет
Всего: нет



Мне не нужно хранить ключи в контейнерах, мне нужно два файла на жестком диске публичный ключ и приватный ключ.

Публичным шифровать, а приватным расшифровывать. Так видимо на криптоапи сделать невозможно.
PM MAIL   Вверх
feodorv
Дата 10.2.2012, 19:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(tofreesky @  10.2.2012,  18:53 Найти цитируемый пост)
мне нужно два файла на жестком диске публичный ключ и приватный ключ.

Что именно диктует такую необходимость?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
tofreesky
Дата 10.2.2012, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 152
Регистрация: 9.6.2010

Репутация: нет
Всего: нет



Как мне отдавать пользователям публичный ключ, и носить с собой программу работающую с приватным ключом?
PM MAIL   Вверх
feodorv
Дата 10.2.2012, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(tofreesky @  10.2.2012,  19:56 Найти цитируемый пост)
Как мне отдавать пользователям публичный ключ, и носить с собой программу работающую с приватным ключом?

Это возможно, схему распишу немного позже.


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 11.2.2012, 00:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Бр, устал бороться, экспорт работает, импорт - нет ((( Ошибка NTE_BAD_VER... Хотя вряд ли это с криптопровайдером связано)))

Экспорт:
Код

#include <Windows.h>
#include <WinCrypt.h>
#include <stdio.h>

#pragma comment (lib, "advapi32.lib")

#define KEYSET_NAME "Movable"
#define FILE_NAME "mykey.rsa"

BOOL _ExportKey()
{
  HCRYPTPROV hProv;
  HCRYPTKEY hKey = 0, hPrivKey = 0;
  HCRYPTHASH hHash = 0;
  BOOL isOld = FALSE, success = TRUE;
  const char *password = "password";

  if( CryptAcquireContext( &hProv, KEYSET_NAME, MS_ENHANCED_PROV, PROV_RSA_FULL, 0) )
    isOld = TRUE;
  else if( !CryptAcquireContext( &hProv, KEYSET_NAME, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) )
  {
    printf( "Не удается создать контекст\n" );
    return FALSE;
  }

  if( success && !CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash) )
  {
    printf( "Не удается создать хэш\n" );
    success = FALSE;
  }
  if( success && !CryptHashData( hHash, (BYTE *) password, sizeof(password)-1, 0) )
  {
    printf( "Не удается добавить данные в хэш\n" );
    success = FALSE;
  }
  if( success && !CryptDeriveKey( hProv, CALG_RC2, hHash, CRYPT_NO_SALT | 0x00800000, &hKey) )
  {
    printf( "Не удается создать ключ из пароля\n" );
    success = FALSE;
  }

  if( success && isOld && !CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hPrivKey) )
  {
    printf( "Не удается получить приватный ключ из контейнера\n" );
    success = FALSE;
  }
  if( success && !isOld && !CryptGenKey( hProv, AT_KEYEXCHANGE, 1024<<16 | CRYPT_EXPORTABLE, &hPrivKey) )
  {
    printf( "Не удается создать ключ RSA для обмена\n" );
    success = FALSE;
  }

  if( success )
  {
    DWORD dwLen = 0;
    BYTE *key = NULL;

    if( !CryptExportKey( hPrivKey, hKey, PRIVATEKEYBLOB, 0, NULL, &dwLen) )
      success = FALSE;

    if( success && (key = (BYTE *) malloc( dwLen )) == NULL )
    {
      printf( "Ошибка выделения памяти\n" );
      success = FALSE;
    }

    if( !CryptExportKey( hPrivKey, hKey, PRIVATEKEYBLOB, 0, key, &dwLen) )
      success = FALSE;

    if( !success )
      printf( "Не удается экспортировать приватный ключ RSA для обмена\n" );
    else
    {
      HANDLE hFile;
      if( (hFile = CreateFileA( FILE_NAME, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE )
      {
        if( !WriteFile( hFile, key, dwLen, &dwLen, NULL) )
          printf( "Не удается сохранить приватный ключ RSA для обмена в файл\n" );
        CloseHandle( hFile );
      }
      else
      {
        printf( "Не удается создать файл %s\n", FILE_NAME);
        success = FALSE;
      }
    }

    if( key != NULL ) free( key );
  }

  if( hKey != 0 ) CryptDestroyKey( hKey );
  if( hPrivKey != 0 ) CryptDestroyKey( hPrivKey );
  if( hHash != 0 ) CryptDestroyHash( hHash );
  CryptReleaseContext( hProv, 0);

  if( success ) printf( "Приватный ключ экспортирован успешно\n" );
  return success;
}

int main()
{
  return _ExportKey() ? 0 : -1;
}


Импорт:
Код

#include <Windows.h>
#include <WinCrypt.h>
#include <stdio.h>

#pragma comment (lib, "advapi32.lib")

#define KEYSET_NAME "Movable2"
#define FILE_NAME "mykey.rsa"

unsigned char *_FileContent( const char *fileName, DWORD *plength)
{
  HANDLE hFile;
  BY_HANDLE_FILE_INFORMATION info;
  unsigned char *content;
  BOOL success = TRUE;
  DWORD dwLen;

  if( (hFile = CreateFileA( fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE )
  {
    printf( "Не удается открыть файл %s\n", fileName);
    success = FALSE;
  }

  if( success && !GetFileInformationByHandle( hFile, &info) )
  {
    printf( "Ошибка получения атрибутов файла %s\n", fileName);
    success = FALSE;
  }

  if( success )
    if( (info.nFileSizeHigh > 0 || info.nFileSizeLow > 16*1024) )
    {
      printf( "Файл %s слишком большой\n", fileName);
      success = FALSE;
    }
    else
      dwLen = *plength = info.nFileSizeLow;

  if( success && (content = (unsigned char *) malloc( dwLen )) == NULL )
  {
    printf( "Ошибка выделения памяти\n" );
    success = FALSE;
  }

  if( success && !ReadFile( hFile, content, *plength, &dwLen, NULL) )
  {
    printf( "Ошибка чтения файла %s\n", fileName);
    success = FALSE;
  }

  if( success && *plength != dwLen )
  {
    printf( "Неправильное чтение файла %s\n", fileName);
    success = FALSE;
  }

  if( hFile != INVALID_HANDLE_VALUE ) CloseHandle( hFile );
  if( !success && content != NULL )
  {
    free( content );
    content = NULL;
  }

  return content;
}

BOOL _ImportKey()
{
  HCRYPTPROV hProv;
  HCRYPTKEY hKey = 0, hPrivKey = 0;
  HCRYPTHASH hHash = 0;
  BOOL isOld = FALSE, success = TRUE;
  const char *password = "password";

  if( CryptAcquireContext( &hProv, KEYSET_NAME, MS_ENHANCED_PROV, PROV_RSA_FULL, 0) )
    isOld = TRUE;
  else if( !CryptAcquireContext( &hProv, KEYSET_NAME, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) )
  {
    printf( "Не удается создать контекст\n" );
    return FALSE;
  }

  if( success && !CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash) )
  {
    printf( "Не удается создать хэш\n" );
    success = FALSE;
  }
  if( success && !CryptHashData( hHash, (BYTE *) password, sizeof(password)-1, 0) )
  {
    printf( "Не удается добавить данные в хэш\n" );
    success = FALSE;
  }
  if( success && !CryptDeriveKey( hProv, CALG_RC2, hHash, CRYPT_NO_SALT | 0x00800000, &hKey) )
  {
    printf( "Не удается создать ключ из пароля\n" );
    success = FALSE;
  }

  if( success )
  {
    DWORD dwLen;
    BYTE *key = (BYTE *) _FileContent( FILE_NAME, &dwLen);
    if( key == NULL ) success = FALSE;

    if( success && !CryptImportKey( hProv, key, dwLen, hKey, CRYPT_EXPORTABLE, &hPrivKey) )
    {
      printf( "Не удается импортировать приватный ключ RSA для обмена, error %x\n", GetLastError());
      success = FALSE;
    }

    if( key != NULL ) free( key );
  }

  if( hKey != 0 ) CryptDestroyKey( hKey );
  if( hPrivKey != 0 ) CryptDestroyKey( hPrivKey );
  if( hHash != 0 ) CryptDestroyHash( hHash );
  CryptReleaseContext( hProv, 0);

  if( success ) printf( "Приватный ключ импортирован успешно\n" );
  return success;
}

int main()
{
  return _ImportKey() ? 0 : -1;
}


Это сообщение отредактировал(а) feodorv - 28.5.2014, 18:52


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1095 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.