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

Поиск:

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


Бывалый
*


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

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



Весь листинг из примеров из rsdn. Вопрос -- почему входной файл расшифровывается тем же публичным ключом, ведь должен приватным.

Код

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

#define BUFFER_SIZE (1<<14)

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

RSAPubKey1024 GL_pubkey;

const WCHAR CN[] = TEXT("");

void ProcessFile(char *_InFile, char *_OutFile, char *_KeyFile, char Type)
{
 HCRYPTPROV hProv;
 if(!::CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL,0)) //получаем контекст
    {
        puts("ЌҐ г¤ Ґвбп Ї®«гзЁвм Є®­вҐЄбв\n");
        return;
    }

    HANDLE hInFile;
    if((hInFile=::CreateFileA(_InFile, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL))!=INVALID_HANDLE_VALUE) //открываем входной файл
    {
        HANDLE hOutFile;
        if((hOutFile=::CreateFileA(_OutFile, GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL))!=INVALID_HANDLE_VALUE) //открываем выходной файл
        {
            HANDLE hKeyFile;
            if((hKeyFile=::CreateFileA(_KeyFile, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL))!=INVALID_HANDLE_VALUE) //открываем файл с публичным ключом
            {
                RSAPubKey1024 key;
                DWORD dwLen;
                if(::ReadFile(hKeyFile,&key,sizeof(RSAPubKey1024),&dwLen,NULL)) //читаем публичный ключ
                {
                    HCRYPTKEY hPubKey;
                    if(::CryptImportKey(hProv,(BYTE *)&key,sizeof(RSAPubKey1024),NULL,0,&hPubKey)) //и импортируем его
                    {
                        HCRYPTHASH hHash;
                        if(::CryptCreateHash(hProv,CALG_MD5,0,0,&hHash)) //создаем хэш
                        {
                            switch(Type)
                            {
                                case 'e':
                                {
                                    HCRYPTKEY hKey;
                                    if(!::CryptGenKey(hProv,CALG_3DES,CRYPT_EXPORTABLE,&hKey)) //генерируем ключ для 3DES
                                    {
                                        puts("ЌҐ г¤ Ґвбп б®§¤ вм Є«оз 3DES\n");
                                        break;
                                    }
                                    EncFileHeader fh;
                                    dwLen=sizeof(RSA1024KeyExchBLOB);
                                    if(::CryptExportKey(hKey,hPubKey,SIMPLEBLOB,0,(BYTE *)&fh.kb,&dwLen)) //экспортируем ключ 3DES
                                    {
                                        DWORD dwSzLow,dwSzHigh;
                                        dwSzLow=::GetFileSize(hInFile,&dwSzHigh); //получаем размер исходного файла
                                        unsigned __int64 fSize=(dwSzHigh<<32)+dwSzLow;
                                        fh.fSize=fSize;
                                        if(::WriteFile(hOutFile,&fh,sizeof(EncFileHeader),&dwLen,NULL)) //пишем ключ и размер исходного файла
                                        {
                                            BYTE buf[BUFFER_SIZE+8]; //8 - запас на padding
                                            while(fSize)
                                            {
                                                if(!::ReadFile(hInFile,buf,BUFFER_SIZE,&dwLen,NULL)) //читаем блок данных
                                                {
                                                    puts("ЋиЁЎЄ  з⥭Ёп д ©« \n");
                                                    break;
                                                }
                                                dwSzLow=dwLen;
                                                if(!::CryptEncrypt(hKey,hHash,fSize<=BUFFER_SIZE,0,buf,&dwSzLow,sizeof(buf))) //шифруем и хешируем его
                                                {
                                                    puts("ЋиЁЎЄ  иЁда®ў ­Ёп\n");
                                                    break;
                                                }
                                                if(!::WriteFile(hOutFile,buf,dwSzLow,&dwSzLow,NULL))
                                                {
                                                    puts("ЋиЁЎЄ  § ЇЁбЁ\n");
                                                    break;
                                                }
                                                fSize-=dwLen;
                                            }
                                            if(!fSize) //все зашифровали нормально
                                            {                                                
                                                dwLen=sizeof(buf);
                                                if(::CryptSignHash(hHash,AT_SIGNATURE,NULL,0,buf,&dwLen)) //подписываем хэш
                                                {
                                                    if(!::WriteFile(hOutFile,buf,dwLen,&dwLen,NULL)) puts("ЋиЁЎЄ  § ЇЁбЁ еҐи  ў д ©«\n");
                                                    else puts("˜Ёда®ў ­ЁҐ гбЇҐи­® § ўҐа襭®\n");
                                                }
                                                else puts("ЌҐ г¤ Ґвбп Ї®¤ЇЁб вм д ©«\n");
                                            }
                                        }
                                        else puts("ЌҐ г¤ Ґвбп б®еа ­Ёвм Є«оз 3DES\n");
                                    }
                                    else puts("ЌҐ г¤ Ґвбп нЄбЇ®авЁа®ў вм Є«оз 3DES\n");
                                    ::CryptDestroyKey(hKey);
                                    break;
                                }
                                case 'd':
                                {
                                    HCRYPTKEY hPrivKey;
                                    if(!::CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hPrivKey)) //достаем приватный ключ пользователя
                                    {
                                        puts("ЌҐ г¤ Ґвбп Ї®«гзЁвм ЇаЁў в­л© Є«оз Ё§ Є®­вҐ©­Ґа \n");
                                        break;
                                    }
                                    EncFileHeader fh;
                                    if(::ReadFile(hInFile,&fh,sizeof(fh),&dwLen,NULL))
                                    {
                                        HCRYPTKEY hKey;
                                        if(::CryptImportKey(hProv,(BYTE *)&fh.kb,sizeof(RSA1024KeyExchBLOB),hPrivKey,0,&hKey)) //импортируем сессионный ключ
                                        {
                                            unsigned __int64 fOrgSize=fh.fSize, fEncSize;
                                            DWORD dwSzLow,dwSzHigh;
                                            dwSzLow=GetFileSize(hInFile,&dwSzHigh);
                                            fEncSize=(dwSzHigh<<32)+dwSzLow-sizeof(EncFileHeader)-1024/8; //размер зашифрованных данных
                                            BYTE buf[BUFFER_SIZE];
                                            while(fEncSize)
                                            {
                                                if(!::ReadFile(hInFile,buf,fEncSize>=BUFFER_SIZE?BUFFER_SIZE:(DWORD)fEncSize,&dwLen,NULL))
                                                {
                                                    puts("ЋиЁЎЄ  з⥭Ёп\n");
                                                    break;
                                                }
                                                dwSzLow=dwLen;
                                                if(!::CryptDecrypt(hKey,hHash,fEncSize<=BUFFER_SIZE,0,buf,&dwSzLow)) //расшифровываем данные
                                                {
                                                    puts("ЋиЁЎЄ  ¤ҐиЁда®ў ­Ёп\n");
                                                    break;
                                                }
                                                if(!::WriteFile(hOutFile,buf,fOrgSize>=dwSzLow?dwSzLow:(DWORD)fOrgSize,&dwSzLow,NULL))
                                                {
                                                    puts("ЋиЁЎЄ  § ЇЁбЁ\n");
                                                    break;
                                                }
                                                fEncSize-=dwLen;
                                                fOrgSize-=dwSzLow;
                                            }
                                            if(!fEncSize) //все нормально отработалось
                                            {
                                                if(::ReadFile(hInFile,buf,1024/8,&dwLen,NULL) && dwLen==1024/8) //читаем подпись
                                                {
                                                    if(!::CryptVerifySignature(hHash,buf,1024/8,hPubKey,NULL,0)) puts("ЋиЁЎЄ  Їа®ўҐаЄЁ Ї®¤ЇЁбЁ. ‚®§¬®¦­® д ©« Ўл« Ї®ўаҐ¦¤Ґ­\n");
                                                    else puts("” ©« гбЇҐи­® а биЁда®ў ­\n");
                                                }
                                                else puts("ЌҐ ­ ©¤Ґ­  бЁЈ­ вга  д ©« \n");
                                            }
                                            ::CryptDestroyKey(hKey);
                                        }
                                        else puts("ЌҐ г¤ Ґвбп Ё¬Ї®авЁа®ў вм Є«оз иЁда®ў ­Ёп\n");
                                    }
                                    else puts("ЋиЁЎЄ  з⥭Ёп д ©« \n");
                                    ::CryptDestroyKey(hPrivKey);
                                }
                            }
                            ::CryptDestroyHash(hHash);
                        }
                        else puts("ЌҐ г¤ Ґвбп б®§¤ вм ени\n");
                        ::CryptDestroyKey(hPubKey);
                    }
                    else puts("ЌҐ г¤ Ґвбп Ё¬Ї®авЁа®ў вм ®вЄалвл© Є«оз\n");
                }
                else puts("ЌҐ г¤ Ґвбп Їа®зЁв вм д ©« б ЇгЎ«Ёз­л¬ Є«о祬\n");
                ::CloseHandle(hKeyFile);
            }
            else puts("ЌҐ г¤ Ґвбп ®вЄалвм д ©« б ЇгЎ«Ёз­л¬ Є«о祬\n");
            ::CloseHandle(hOutFile);
        }
        else puts("ЌҐ г¤ Ґвбп ®вЄалвм ўл室­®© д ©«\n");
        ::CloseHandle(hInFile);
    }
    else puts("ЌҐ г¤ Ґвбп ®вЄалвм ўе®¤­®© д ©«\n");
    ::CryptReleaseContext(hProv,0);                
}

void GenerateKey()
{
 HCRYPTPROV hProv;
 if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL,0) && !CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET)) //пытаемся открыть существующий keyset или создать новый
 {
    puts("ЌҐ г¤ Ґвбп б®§¤ вм Є®­вҐЄбв\n");
    return;
 }

 HCRYPTKEY hKey;
    if(CryptGenKey(hProv,AT_KEYEXCHANGE,1024<<16,&hKey)) //генерируем 1024-битный ключ для обмена
    {
        RSAPubKey1024 key;
        DWORD dwLen=sizeof(RSAPubKey1024);
        if(CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,(BYTE*)&key,&dwLen)) //экспортируем ключ
        {
            HANDLE hFile;
            if((hFile=CreateFileA("key.rsa", GENERIC_WRITE, FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))!=INVALID_HANDLE_VALUE)
            {
                if(WriteFile(hFile,&key,dwLen,&dwLen,NULL)) //сохраняем файл
                {

                }
                else puts("ЌҐ г¤ Ґвбп б®еа ­Ёвм ЇгЎ«Ёз­л© Є«оз RSA ¤«п ®Ў¬Ґ­  ў д ©«\n");
                CloseHandle(hFile);
            }
            else puts("ЌҐ г¤ Ґвбп б®§¤ вм д ©« pubkey.xch\n");
        }
        else puts("ЌҐ г¤ Ґвбп нЄбЇ®авЁа®ў вм ЇгЎ«Ёз­л© Є«оз RSA ¤«п ®Ў¬Ґ­ \n");
        CryptDestroyKey(hKey);
    }
    else puts("ЌҐ г¤ Ґвбп б®§¤ вм Є«оз RSA ¤«п ®Ў¬Ґ­ \n");
    CryptReleaseContext(hProv,0);
}

int main()
{
 GenerateKey();
 ProcessFile("in.bin", "out.bin", "key.rsa", 'e');
 ProcessFile("out.bin", "out_d.bin", "key.rsa", 'd');
 ExitProcess(0);
 return 0;
}



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


Бывалый
*


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

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



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

Ошибка импорта 0x80090003 (NTE_BAD_KEY)

Это сообщение отредактировал(а) tofreesky - 8.2.2012, 23:47
PM MAIL   Вверх
volatile
Дата 9.2.2012, 00:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

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



tofreesky, очень перегруженная функция. Скорей всего запутались где-то в скобках.
Такой код понять трудно даже вам самому, почему вы думаете что другим будет легче?

Цитата(tofreesky @  8.2.2012,  23:06 Найти цитируемый пост)
puts("ЌҐ г¤ Ґвбп Ї®«гзЁвм ЇаЁў в­л© Є«оз Ё§ Є®­вҐ©­Ґа \n");

Вот наприме строки у вас очень не плохо получилось зашифровать smile

tofreesky, поробуйте разбить функцию на несколько штук, вменяемого размера.
Возможно после этого, и помощь уже не понадобится
PM MAIL   Вверх
tofreesky
Дата 9.2.2012, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Я же сказал что это с rsdn, тут код не большой и понятный. Так по делу есть какие-то мысли? 

На 104 строке где расшифровка, ведь передаваемый приватный ключ был зашифрован сессионным, который нигде не сохранен, из-за этого и ошибка?
PM MAIL   Вверх
feodorv
Дата 9.2.2012, 01:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(tofreesky @  8.2.2012,  23:06 Найти цитируемый пост)
Вопрос -- почему входной файл расшифровывается тем же публичным ключом, ведь должен приватным.

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

Цитата(tofreesky @  8.2.2012,  23:39 Найти цитируемый пост)
если запустить программу два раза

Цитата(tofreesky @  8.2.2012,  23:39 Найти цитируемый пост)
публичный ключ для расшифровывания не подойдет

Вот это странно, так как:
Код

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



Это сообщение отредактировал(а) feodorv - 9.2.2012, 02:49


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


Бывалый
*


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

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



Все равно ничего нового, вот немного измененный код:

Код

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

#define BUFFER_SIZE (1<<14)

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

RSAPubKey1024 GL_pubkey;

const WCHAR CN[] = TEXT("");

void ProcessFile(char *_InFile, char *_OutFile, char *_KeyFile, char Type)
{
 HCRYPTPROV hProv;
 if(!::CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL,0)) //получаем контекст
    {
        puts("ЌҐ г¤ Ґвбп Ї®«гзЁвм Є®­вҐЄбв\n");
        return;
    }

    HANDLE hInFile;
    if((hInFile=::CreateFileA(_InFile, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL))!=INVALID_HANDLE_VALUE) //открываем входной файл
    {
        HANDLE hOutFile;
        if((hOutFile=::CreateFileA(_OutFile, GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL))!=INVALID_HANDLE_VALUE) //открываем выходной файл
        {
            HANDLE hKeyFile;
            if((hKeyFile=::CreateFileA(_KeyFile, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL))!=INVALID_HANDLE_VALUE) //открываем файл с публичным ключом
            {
                RSAPubKey1024 key;
                DWORD dwLen;
                if(::ReadFile(hKeyFile,&key,sizeof(RSAPubKey1024),&dwLen,NULL)) //читаем публичный ключ
                {
                    HCRYPTKEY hPubKey;
                    if(::CryptImportKey(hProv,(BYTE *)&key,sizeof(RSAPubKey1024),NULL,0,&hPubKey)) //и импортируем его
                    {
                        HCRYPTHASH hHash;
                        if(::CryptCreateHash(hProv,CALG_MD5,0,0,&hHash)) //создаем хэш
                        {
                            switch(Type)
                            {
                                case 'e':
                                {
                                    HCRYPTKEY hKey;
                                    if(!::CryptGenKey(hProv,CALG_3DES,CRYPT_EXPORTABLE,&hKey)) //генерируем ключ для 3DES
                                    {
                                        puts("ЌҐ г¤ Ґвбп б®§¤ вм Є«оз 3DES\n");
                                        break;
                                    }
                                    EncFileHeader fh;
                                    dwLen=sizeof(RSA1024KeyExchBLOB);
                                    if(::CryptExportKey(hKey,hPubKey,SIMPLEBLOB,0,(BYTE *)&fh.kb,&dwLen)) //экспортируем ключ 3DES
                                    {
                                        DWORD dwSzLow,dwSzHigh;
                                        dwSzLow=::GetFileSize(hInFile,&dwSzHigh); //получаем размер исходного файла
                                        unsigned __int64 fSize=(dwSzHigh<<32)+dwSzLow;
                                        fh.fSize=fSize;
                                        if(::WriteFile(hOutFile,&fh,sizeof(EncFileHeader),&dwLen,NULL)) //пишем ключ и размер исходного файла
                                        {
                                            BYTE buf[BUFFER_SIZE+8]; //8 - запас на padding
                                            while(fSize)
                                            {
                                                if(!::ReadFile(hInFile,buf,BUFFER_SIZE,&dwLen,NULL)) //читаем блок данных
                                                {
                                                    puts("ЋиЁЎЄ  з⥭Ёп д ©« \n");
                                                    break;
                                                }
                                                dwSzLow=dwLen;
                                                if(!::CryptEncrypt(hKey,hHash,fSize<=BUFFER_SIZE,0,buf,&dwSzLow,sizeof(buf))) //шифруем и хешируем его
                                                {
                                                    puts("ЋиЁЎЄ  иЁда®ў ­Ёп\n");
                                                    break;
                                                }
                                                if(!::WriteFile(hOutFile,buf,dwSzLow,&dwSzLow,NULL))
                                                {
                                                    puts("ЋиЁЎЄ  § ЇЁбЁ\n");
                                                    break;
                                                }
                                                fSize-=dwLen;
                                            }
                                            if(!fSize) //все зашифровали нормально
                                            {                                                
                                                dwLen=sizeof(buf);
                                                if(::CryptSignHash(hHash,AT_SIGNATURE,NULL,0,buf,&dwLen)) //подписываем хэш
                                                {
                                                    if(!::WriteFile(hOutFile,buf,dwLen,&dwLen,NULL)) puts("ЋиЁЎЄ  § ЇЁбЁ еҐи  ў д ©«\n");
                                                    else puts("˜Ёда®ў ­ЁҐ гбЇҐи­® § ўҐа襭®\n");
                                                }
                                                else puts("ЌҐ г¤ Ґвбп Ї®¤ЇЁб вм д ©«\n");
                                            }
                                        }
                                        else puts("ЌҐ г¤ Ґвбп б®еа ­Ёвм Є«оз 3DES\n");
                                    }
                                    else puts("ЌҐ г¤ Ґвбп нЄбЇ®авЁа®ў вм Є«оз 3DES\n");
                                    ::CryptDestroyKey(hKey);
                                    break;
                                }
                                case 'd':
                                {
                                    HCRYPTKEY hPrivKey;
                                    if(!::CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hPrivKey)) //достаем приватный ключ пользователя
                                    {
                                        puts("ЌҐ г¤ Ґвбп Ї®«гзЁвм ЇаЁў в­л© Є«оз Ё§ Є®­вҐ©­Ґа \n");
                                        break;
                                    }
                                    EncFileHeader fh;
                                    if(::ReadFile(hInFile,&fh,sizeof(fh),&dwLen,NULL))
                                    {
                                        HCRYPTKEY hKey;
                                        if(::CryptImportKey(hProv,(BYTE *)&fh.kb,sizeof(RSA1024KeyExchBLOB),hPrivKey,0,&hKey)) //импортируем сессионный ключ
                                        {
                                            unsigned __int64 fOrgSize=fh.fSize, fEncSize;
                                            DWORD dwSzLow,dwSzHigh;
                                            dwSzLow=GetFileSize(hInFile,&dwSzHigh);
                                            fEncSize=(dwSzHigh<<32)+dwSzLow-sizeof(EncFileHeader)-1024/8; //размер зашифрованных данных
                                            BYTE buf[BUFFER_SIZE];
                                            while(fEncSize)
                                            {
                                                if(!::ReadFile(hInFile,buf,fEncSize>=BUFFER_SIZE?BUFFER_SIZE:(DWORD)fEncSize,&dwLen,NULL))
                                                {
                                                    puts("ЋиЁЎЄ  з⥭Ёп\n");
                                                    break;
                                                }
                                                dwSzLow=dwLen;
                                                if(!::CryptDecrypt(hKey,hHash,fEncSize<=BUFFER_SIZE,0,buf,&dwSzLow)) //расшифровываем данные
                                                {
                                                    puts("ЋиЁЎЄ  ¤ҐиЁда®ў ­Ёп\n");
                                                    break;
                                                }
                                                if(!::WriteFile(hOutFile,buf,fOrgSize>=dwSzLow?dwSzLow:(DWORD)fOrgSize,&dwSzLow,NULL))
                                                {
                                                    puts("ЋиЁЎЄ  § ЇЁбЁ\n");
                                                    break;
                                                }
                                                fEncSize-=dwLen;
                                                fOrgSize-=dwSzLow;
                                            }
                                            if(!fEncSize) //все нормально отработалось
                                            {
                                                if(::ReadFile(hInFile,buf,1024/8,&dwLen,NULL) && dwLen==1024/8) //читаем подпись
                                                {
                                                    if(!::CryptVerifySignature(hHash,buf,1024/8,hPubKey,NULL,0)) puts("ЋиЁЎЄ  Їа®ўҐаЄЁ Ї®¤ЇЁбЁ. ‚®§¬®¦­® д ©« Ўл« Ї®ўаҐ¦¤Ґ­\n");
                                                    else puts("” ©« гбЇҐи­® а биЁда®ў ­\n");
                                                }
                                                else puts("ЌҐ ­ ©¤Ґ­  бЁЈ­ вга  д ©« \n");
                                            }
                                            ::CryptDestroyKey(hKey);
                                        }
                                        else puts("ЌҐ г¤ Ґвбп Ё¬Ї®авЁа®ў вм Є«оз иЁда®ў ­Ёп\n");
                                    }
                                    else puts("ЋиЁЎЄ  з⥭Ёп д ©« \n");
                                    ::CryptDestroyKey(hPrivKey);
                                }
                            }
                            ::CryptDestroyHash(hHash);
                        }
                        else puts("ЌҐ г¤ Ґвбп б®§¤ вм ени\n");
                        ::CryptDestroyKey(hPubKey);
                    }
                    else puts("ЌҐ г¤ Ґвбп Ё¬Ї®авЁа®ў вм ®вЄалвл© Є«оз\n");
                }
                else puts("ЌҐ г¤ Ґвбп Їа®зЁв вм д ©« б ЇгЎ«Ёз­л¬ Є«о祬\n");
                ::CloseHandle(hKeyFile);
            }
            else puts("ЌҐ г¤ Ґвбп ®вЄалвм д ©« б ЇгЎ«Ёз­л¬ Є«о祬\n");
            ::CloseHandle(hOutFile);
        }
        else puts("ЌҐ г¤ Ґвбп ®вЄалвм ўл室­®© д ©«\n");
        ::CloseHandle(hInFile);
    }
    else puts("ЌҐ г¤ Ґвбп ®вЄалвм ўе®¤­®© д ©«\n");
    ::CryptReleaseContext(hProv,0);                
}

void GenerateKey()
{
 HCRYPTPROV hProv;
 if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL,0) && !CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET)) //пытаемся открыть существующий keyset или создать новый
 {
    puts("ЌҐ г¤ Ґвбп б®§¤ вм Є®­вҐЄбв\n");
    return;
 }

 HCRYPTKEY hKey;
    if(CryptGenKey(hProv,AT_KEYEXCHANGE,1024<<16 | CRYPT_EXPORTABLE,&hKey)) //генерируем 1024-битный ключ для обмена
    {
        RSAPubKey1024 key;
        DWORD dwLen=sizeof(RSAPubKey1024);
        if(CryptExportKey(hKey,NULL,PUBLICKEYBLOB,0,(BYTE*)&key,&dwLen)) //экспортируем ключ
        {
            HANDLE hFile;
            if((hFile=CreateFileA("key_pub.rsa", GENERIC_WRITE, FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))!=INVALID_HANDLE_VALUE)
            {
                if(WriteFile(hFile,&key,dwLen,&dwLen,NULL)) //сохраняем файл
                {

                }
                else puts("ЌҐ г¤ Ґвбп б®еа ­Ёвм ЇгЎ«Ёз­л© Є«оз RSA ¤«п ®Ў¬Ґ­  ў д ©«\n");
                CloseHandle(hFile);
            }
            else puts("ЌҐ г¤ Ґвбп б®§¤ вм д ©« pubkey.xch\n");
        }
        else puts("ЌҐ г¤ Ґвбп нЄбЇ®авЁа®ў вм ЇгЎ«Ёз­л© Є«оз RSA ¤«п ®Ў¬Ґ­ \n");

        /////////////////
        RSAPrivKey1024 pkey;
        dwLen=sizeof(RSAPrivKey1024);
        if(CryptExportKey(hKey,NULL,PRIVATEKEYBLOB,0, (BYTE*)&key, &dwLen)) //экспортируем ключ
        {
            HANDLE hFile;
            if((hFile=CreateFileA("key_prv.rsa", GENERIC_WRITE, FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))!=INVALID_HANDLE_VALUE)
            {
                if(WriteFile(hFile,&key,dwLen,&dwLen,NULL)) //сохраняем файл
                {

                }
                else puts("ЌҐ г¤ Ґвбп б®еа ­Ёвм ЇгЎ«Ёз­л© Є«оз RSA ¤«п ®Ў¬Ґ­  ў д ©«\n");
                CloseHandle(hFile);
            }
            else puts("ЌҐ г¤ Ґвбп б®§¤ вм д ©« pubkey.xch\n");
        }
        else puts("ЌҐ г¤ Ґвбп нЄбЇ®авЁа®ў вм ЇгЎ«Ёз­л© Є«оз RSA ¤«п ®Ў¬Ґ­ \n");
        
        CryptDestroyKey(hKey);
    }
    else puts("ЌҐ г¤ Ґвбп б®§¤ вм Є«оз RSA ¤«п ®Ў¬Ґ­ \n");
    CryptReleaseContext(hProv,0);
}

int main()
{
 // GenerateKey();
 // ProcessFile("in.bin", "out.bin", "key_pub.rsa", 'e');
 ProcessFile("out.bin", "out_d.bin", "key_prv.rsa", 'd');
 ExitProcess(0);
 return 0;
}


GenerateKey(); генерирует приватный и публичный ключи 
ProcessFile(); шифрует или расшифровывает в зависимости от четвертого параметра.

Так вот, теперь не выходит расшифровать файл приватным ключом, NTE_BAD_KEY при импорте. В чем дело? 

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


Эксперт
****


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

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



Цитата(tofreesky @  9.2.2012,  10:42 Найти цитируемый пост)
сессионым, а он ни где не сохранятся

Ещё раз. По оригинальному коду MS.

Файл шифруется и расшифровывается симметричным сессионным ключом. Он создаётся при "encode":
Код
CryptGenKey(hProv,CALG_3DES,CRYPT_EXPORTABLE,&hKey)
 и экспортируется в поле kb структуры EncFileHeader 
Код
CryptExportKey(hKey,hPubKey,SIMPLEBLOB,0,(BYTE *)&fh.kb,&dwLen)
. Поскольку просто скопировать сессионный ключ нельзя, иначе он будет виден кому угодно, то его шифруют, и шифруют открытым пользовательским ключом:
Цитата

BOOL WINAPI CryptExportKey(
  HCRYPTKEY hKey, 
  HCRYPTKEY hExpKey, 
  DWORD dwBlobType, 
  DWORD dwFlags, 
  BYTE* pbData, 
  DWORD* pdwDataLen
);

Parameters
hKey 
[in] Handle to the key to be exported. 
hExpKey 
[in] Handle to a cryptographic key of the destination user. The key data within the exported key BLOB is encrypted using this key. This ensures that only the destination user is able to make use of the key BLOB. 

Таким образом, hKey (сессионный ключ) шифруется с помощью hPubKey (открытый пользовательский ключ), и всё это записывается в виде набора байт в kb. А уже потом структура EncFileHeader вместе с зашифрованным сессионным ключом сбрасывается в выходный файл в виде заголовка этого файла, после которого будет записано шифруемое содержимое оригинального файла. Поэтому:
Цитата(tofreesky @  9.2.2012,  10:42 Найти цитируемый пост)
шифруется еще и сессионым, а он ни где не сохранятся

в корне не верно:
  • сессионный ключ шифруется открытым и сохраняется в заголовке выходного файла
  • файл шифруется только сессионным ключом и записывается в выходной файл после заголовка
Ваш код ещё не смотрел, пока не хватает времени...

Добавлено через 5 минут и 27 секунд
И для полной картины не хватает
Код

#include "tools.h"



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


Бывалый
*


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

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



Все равно не понятно почему приватным ключом не удается  расшифровать файл?

tools.h
Код

#if !defined(_TOOLS_H__32E06D4B_5085_4E03_8180_58CC1ECA4E6E__INCLUDED_)
#define _TOOLS_H__32E06D4B_5085_4E03_8180_58CC1ECA4E6E__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

template<int bitlen> struct RSAPubKey
{
    PUBLICKEYSTRUC  publickeystruc ;
    RSAPUBKEY rsapubkey;
    BYTE modulus[bitlen/8];
};

template<int bitlen> struct RSAPrivKey
{
    RSAPubKey<bitlen> pubkey;
    BYTE prime1[bitlen/16];
    BYTE prime2[bitlen/16];
    BYTE exponent1[bitlen/16];
    BYTE exponent2[bitlen/16];
    BYTE coefficient[bitlen/16];
    BYTE privateExponent[bitlen/8];
};

typedef RSAPubKey<1024> RSAPubKey1024;
typedef RSAPrivKey<1024> RSAPrivKey1024;

template<int bitlen> struct RSAKeyExchBLOB
{
    PUBLICKEYSTRUC publickeystruc ;
    ALG_ID algid;
    BYTE encryptedkey[bitlen/8];
};

typedef RSAKeyExchBLOB<1024> RSA1024KeyExchBLOB;

#endif

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


Бывалый
*


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

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



В общем надо забить на эту все кривую реализацию RSA у MS, на другой системе уже падает на:

Самом начале функции
Код

 if(!::CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL,0)) //получаем контекст


С ошибкой NTE_BAD_KEYSET.


Есть ли нормальные либы для RSA, только не  по 25 мб, которые.
PM MAIL   Вверх
feodorv
Дата 9.2.2012, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(tofreesky @  9.2.2012,  17:22 Найти цитируемый пост)
Все равно не понятно почему приватным ключом не удается  расшифровать файл?

Прилизал немного код и перевёл в Си:
Код

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

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

struct RSAPubKey1024
{
  PUBLICKEYSTRUC publickeystruc;
  RSAPUBKEY rsapubkey;
  BYTE modulus[1024/8];
};

struct RSAPrivKey1024
{
  struct RSAPubKey1024 pubkey;
  BYTE prime1[1024/16];
  BYTE prime2[1024/16];
  BYTE exponent1[1024/16];
  BYTE exponent2[1024/16];
  BYTE coefficient[1024/16];
  BYTE privateExponent[1024/8];
};

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;

void ProcessFile(char *_InFile, char *_OutFile, char *_KeyFile, char Type)
{
  HCRYPTPROV hProv;
  HANDLE hInFile;
  BOOL success = TRUE;

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

  if( (hInFile = CreateFileA( _InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE ) //открываем входной файл
  {
    HANDLE hOutFile;
    if( (hOutFile = CreateFileA( _OutFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL)) != INVALID_HANDLE_VALUE ) //открываем выходной файл
    {
      HANDLE hKeyFile;
      if( (hKeyFile = CreateFileA( _KeyFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE ) //открываем файл с публичным ключом
      {
        struct RSAPubKey1024 key;
        DWORD dwLen;
        if( ReadFile( hKeyFile, &key, sizeof(struct RSAPubKey1024), &dwLen, NULL) ) //читаем публичный ключ
        {
          HCRYPTKEY hPubKey;
          if( CryptImportKey( hProv, (BYTE *) &key, sizeof(struct RSAPubKey1024), NULL, 0, &hPubKey)) //и импортируем его
          {
            HCRYPTHASH hHash;
            if( CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash) ) //создаем хэш
            {
              switch(Type)
              {
                case 'e':
                {
                  HCRYPTKEY hKey;
                  EncFileHeader fh;
                  if( !CryptGenKey( hProv, CALG_3DES, CRYPT_EXPORTABLE, &hKey) ) //генерируем ключ для 3DES
                  {
                    puts( "Не удается создать ключ 3DES\n" );
                    break;
                  }
                  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;
                    fh.fSize = fSize;
                    if( WriteFile( hOutFile, &fh, sizeof(EncFileHeader), &dwLen, NULL) ) //пишем ключ и размер исходного файла
                    {
                      BYTE buf[BUFFER_SIZE+8]; //8 - запас на padding
                      while( fSize )
                      {
                        if( !ReadFile( hInFile, buf, BUFFER_SIZE, &dwLen, NULL) ) //читаем блок данных
                        {
                          puts( "Ошибка чтения файла\n" );
                          break;
                        }
                        dwSzLow = dwLen;
                        if( !CryptEncrypt( hKey, hHash, fSize <= BUFFER_SIZE, 0, buf, &dwSzLow, sizeof(buf)) ) //шифруем и хешируем его
                        {
                          puts( "Ошибка шифрования\n" );
                          break;
                        }
                        if( !WriteFile( hOutFile, buf, dwSzLow, &dwSzLow, NULL) )
                        {
                          puts( "Ошибка записи\n" );
                          break;
                        }
                        fSize -= dwLen;
                      }
                      if( !fSize ) //все зашифровали нормально
                      {
                        dwLen = sizeof(buf);
                        if( CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, buf, &dwLen) ) //подписываем хэш
                        {
                          if( !WriteFile( hOutFile, buf, dwLen, &dwLen, NULL) )
                            puts( "Ошибка записи хеша в файл\n" );
                          else
                            puts( "Шифрование успешно завершено\n" );
                        }
                        else
                          puts( "Не удается подписать файл\n" );
                      }
                    }
                    else
                      puts( "Не удается сохранить ключ 3DES\n" );
                  }
                  else
                    puts( "Не удается экспортировать ключ 3DES\n" );
                  CryptDestroyKey( hKey );
                  break;
                }

                case 'd':
                {
                  HCRYPTKEY hPrivKey;
                  EncFileHeader fh;
                  if( !CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hPrivKey) ) //достаем приватный ключ пользователя
                  {
                    puts( "Не удается получить приватный ключ из контейнера\n" );
                    break;
                  }
                  if( ReadFile( hInFile, &fh, sizeof(fh), &dwLen,NULL) )
                  {
                    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) )
                        {
                          puts( "Ошибка чтения\n" );
                          break;
                        }
                        dwSzLow = dwLen;
                        if( !CryptDecrypt( hKey, hHash, fEncSize <= BUFFER_SIZE, 0, buf, &dwSzLow) ) //расшифровываем данные
                        {
                          puts( "Ошибка дешифрования\n" );
                          break;
                        }
                        if( !WriteFile( hOutFile, buf, fOrgSize >= dwSzLow ? dwSzLow : (DWORD) fOrgSize, &dwSzLow, NULL) )
                        {
                          puts( "Ошибка записи\n" );
                          break;
                        }
                        fEncSize -= dwLen;
                        fOrgSize -= dwSzLow;
                      }
                      if( !fEncSize ) //все нормально отработалось
                      {
                        if( ReadFile( hInFile, buf, 1024/8, &dwLen, NULL) && dwLen == 1024/8 ) //читаем подпись
                        {
                          if( !CryptVerifySignature( hHash, buf, 1024/8, hPubKey, NULL, 0) )
                            puts( "Ошибка проверки подписи. Возможно файл был поврежден\n" );
                          else
                            puts( "Файл успешно расшифрован\n" );
                        }
                        else
                          puts( "Не найдена сигнатура файла\n" );
                      }
                      CryptDestroyKey( hKey );
                    }
                    else
                      puts( "Не удается импортировать ключ шифрования\n" );
                  }
                  else
                    puts( "Ошибка чтения файла\n");
                  CryptDestroyKey( hPrivKey );
                }
              }
              CryptDestroyHash(hHash);
            }
            else
              puts( "Не удается создать хэш\n" );
            CryptDestroyKey( hPubKey );
          }
          else
            puts( "Не удается импортировать открытый ключ\n" );
        }
        else
          puts( "Не удается прочитать файл с публичным ключем\n" );
        CloseHandle( hKeyFile );
      }
      else
        puts( "Не удается открыть файл с публичным ключем\n" );
      CloseHandle( hOutFile );
    }
    else
      puts("Не удается открыть выходной файл\n");
    CloseHandle(hInFile);
  }
  else
    puts( "Не удается открыть входной файл\n" );

  CryptReleaseContext( hProv, 0);
}

void GenerateKey()
{
  HCRYPTPROV hProv;
  HCRYPTKEY hKey;

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

  if( CryptGenKey( hProv, AT_KEYEXCHANGE, 1024<<16, &hKey) ) //генерируем 1024-битный ключ для обмена
  {
    struct RSAPubKey1024 key;
    DWORD dwLen = sizeof(struct RSAPubKey1024);
    if( CryptExportKey( hKey, NULL, PUBLICKEYBLOB, 0, (BYTE*) &key, &dwLen) ) //экспортируем ключ
    {
      HANDLE hFile;
      if( (hFile = CreateFileA( "key.rsa", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE )
      {
        if( !WriteFile( hFile, &key, dwLen, &dwLen, NULL) ) //сохраняем файл
          puts( "Не удается сохранить публичный ключ RSA для обмена в файл\n" );
        CloseHandle( hFile );
      }
      else
        puts( "Не удается создать файл pubkey.xch\n" );
    }
    else
      puts( "Не удается экспортировать публичный ключ RSA для обмена\n" );
    CryptDestroyKey(hKey);
  }
  else
    puts( "Не удается создать ключ RSA для обмена\n" );

  CryptReleaseContext( hProv, 0);
}

int main()
{
  GenerateKey();
  ProcessFile("in.bin", "out.bin", "key.rsa", 'e');
  ProcessFile("out.bin", "out_d.bin", "key.rsa", 'd');
  ExitProcess(0);
  return 0;
}

Файл нормально зашифровывается и расшифровывается, только подпись не проходит проверку, пока не разобрался, почему.

Добавлено через 13 минут и 53 секунды
Цитата(feodorv @  9.2.2012,  19:07 Найти цитируемый пост)
подпись не проходит проверку, пока не разобрался, почему.

Разобрался. Для подписи использовался приватный AT_SIGNATURE ключ, а для проверки подписи - публичный AT_KEYEXCHANGE ключ. Нестыковочка  smile 

Достаточно в коде 
Код

if( CryptSignHash( hHash, AT_SIGNATURE, NULL, 0, buf, &dwLen) ) //подписываем хэш

поменять AT_SIGNATURE на AT_KEYEXCHANGE и... все работает!!! Всё, даже вариант без 
Код

  GenerateKey();
  ProcessFile("in.bin", "out.bin", "key.rsa", 'e');

 smile 

Это сообщение отредактировал(а) feodorv - 9.2.2012, 19:15


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


Эксперт
****


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

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



Цитата(tofreesky @  9.2.2012,  00:05 Найти цитируемый пост)
тут код не большой и понятный

Что-то я сомневаюсь, что понятный  smile 

Цитата(tofreesky @  9.2.2012,  17:41 Найти цитируемый пост)
В общем надо забить на эту все кривую реализацию RSA у MS

Ха, может, криво где-то в другом месте???


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


Бывалый
*


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

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



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


Эксперт
****


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

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



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

Так это тот же майксрософтовский код, только сизированный smile 
А вот новое это то, что он работает.

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

Не понял, о чём Вы.

Цитата(tofreesky @  9.2.2012,  20:06 Найти цитируемый пост)
приватный ключ не расшифровывает сообщение

Ох... Может Вы имеете в виду, что 
Цитата(tofreesky @  9.2.2012,  10:42 Найти цитируемый пост)
NTE_BAD_KEY при импорте
, но никакого отношения к расшифровке файла, да ещё и приватным(!) ключом это не имеет.



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


Бывалый
*


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

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



Так в чем смысл, это получается симметричное шифрование, а не асимметричность, раз можно зашифровать и расшифровать одним ключом.

Добавлено через 10 минут и 13 секунд
Код

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

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

struct RSAPubKey1024
{
  PUBLICKEYSTRUC publickeystruc;
  RSAPUBKEY rsapubkey;
  BYTE modulus[1024/8];
};

struct RSAPrivKey1024
{
  struct RSAPubKey1024 pubkey;
  BYTE prime1[1024/16];
  BYTE prime2[1024/16];
  BYTE exponent1[1024/16];
  BYTE exponent2[1024/16];
  BYTE coefficient[1024/16];
  BYTE privateExponent[1024/8];
};

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;

void ProcessFile(char *_InFile, char *_OutFile, char *_KeyFile, char Type)
{
  HCRYPTPROV hProv;
  HANDLE hInFile;
  BOOL success = TRUE;
  if( !CryptAcquireContext( &hProv, NULL, MS_ENHANCED_PROV,PROV_RSA_FULL, 0) ) //получаем контекст
  {
    puts( "Не удается получить контекст\n" );
    return;
  }
  if( (hInFile = CreateFileA( _InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE ) //открываем входной файл
  {
    HANDLE hOutFile;
    if( (hOutFile = CreateFileA( _OutFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL)) != INVALID_HANDLE_VALUE ) //открываем выходной файл
    {
      HANDLE hKeyFile;
      if( (hKeyFile = CreateFileA( _KeyFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE ) //открываем файл с публичным ключом
      {
        struct RSAPubKey1024 key;
        DWORD dwLen;
        if( ReadFile( hKeyFile, &key, sizeof(struct RSAPubKey1024), &dwLen, NULL) ) //читаем публичный ключ
        {
          HCRYPTKEY hPubKey;
          if( CryptImportKey( hProv, (BYTE *) &key, sizeof(struct RSAPubKey1024), NULL, 0, &hPubKey)) //и импортируем его
          {
            HCRYPTHASH hHash;
            if( CryptCreateHash( hProv, CALG_MD5, 0, 0, &hHash) ) //создаем хэш
            {
              switch(Type)
              {
                case 'e':
                {
                  HCRYPTKEY hKey;
                  EncFileHeader fh;
                  if( !CryptGenKey( hProv, CALG_3DES, CRYPT_EXPORTABLE, &hKey) ) //генерируем ключ для 3DES
                  {
                    puts( "Не удается создать ключ 3DES\n" );
                    break;
                  }
                  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;
                    fh.fSize = fSize;
                    if( WriteFile( hOutFile, &fh, sizeof(EncFileHeader), &dwLen, NULL) ) //пишем ключ и размер исходного файла
                    {
                      BYTE buf[BUFFER_SIZE+8]; //8 - запас на padding
                      while( fSize )
                      {
                        if( !ReadFile( hInFile, buf, BUFFER_SIZE, &dwLen, NULL) ) //читаем блок данных
                        {
                          puts( "Ошибка чтения файла\n" );
                          break;
                        }
                        dwSzLow = dwLen;
                        if( !CryptEncrypt( hKey, hHash, fSize <= BUFFER_SIZE, 0, buf, &dwSzLow, sizeof(buf)) ) //шифруем и хешируем его
                        {
                          puts( "Ошибка шифрования\n" );
                          break;
                        }
                        if( !WriteFile( hOutFile, buf, dwSzLow, &dwSzLow, NULL) )
                        {
                          puts( "Ошибка записи\n" );
                          break;
                        }
                        fSize -= dwLen;
                      }
                      if( !fSize ) //все зашифровали нормально
                      {
                        dwLen = sizeof(buf);
                        if( CryptSignHash( hHash, AT_KEYEXCHANGE, NULL, 0, buf, &dwLen) ) //подписываем хэш
                        {
                          if( !WriteFile( hOutFile, buf, dwLen, &dwLen, NULL) )
                            puts( "Ошибка записи хеша в файл\n" );
                          else
                            puts( "Шифрование успешно завершено\n" );
                        }
                        else
                          puts( "Не удается подписать файл\n" );
                      }
                    }
                    else
                      puts( "Не удается сохранить ключ 3DES\n" );
                  }
                  else
                    puts( "Не удается экспортировать ключ 3DES\n" );
                  CryptDestroyKey( hKey );
                  break;
                }
                case 'd':
                {
                  HCRYPTKEY hPrivKey;
                  EncFileHeader fh;
                  if( !CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hPrivKey) ) //достаем приватный ключ пользователя
                  {
                    puts( "Не удается получить приватный ключ из контейнера\n" );
                    break;
                  }
                  if( ReadFile( hInFile, &fh, sizeof(fh), &dwLen,NULL) )
                  {
                    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) )
                        {
                          puts( "Ошибка чтения\n" );
                          break;
                        }
                        dwSzLow = dwLen;
                        if( !CryptDecrypt( hKey, hHash, fEncSize <= BUFFER_SIZE, 0, buf, &dwSzLow) ) //расшифровываем данные
                        {
                          puts( "Ошибка дешифрования\n" );
                          break;
                        }
                        if( !WriteFile( hOutFile, buf, fOrgSize >= dwSzLow ? dwSzLow : (DWORD) fOrgSize, &dwSzLow, NULL) )
                        {
                          puts( "Ошибка записи\n" );
                          break;
                        }
                        fEncSize -= dwLen;
                        fOrgSize -= dwSzLow;
                      }
                      if( !fEncSize ) //все нормально отработалось
                      {
                        if( ReadFile( hInFile, buf, 1024/8, &dwLen, NULL) && dwLen == 1024/8 ) //читаем подпись
                        {
                          if( !CryptVerifySignature( hHash, buf, 1024/8, hPubKey, NULL, 0) )
                            puts( "Ошибка проверки подписи. Возможно файл был поврежден\n" );
                          else
                            puts( "Файл успешно расшифрован\n" );
                        }
                        else
                          puts( "Не найдена сигнатура файла\n" );
                      }
                      CryptDestroyKey( hKey );
                    }
                    else
                      puts( "Не удается импортировать ключ шифрования\n" );
                  }
                  else
                    puts( "Ошибка чтения файла\n");
                  CryptDestroyKey( hPrivKey );
                }
              }
              CryptDestroyHash(hHash);
            }
            else
              puts( "Не удается создать хэш\n" );
            CryptDestroyKey( hPubKey );
          }
          else
            puts( "Не удается импортировать открытый ключ\n" );
        }
        else
          puts( "Не удается прочитать файл с публичным ключем\n" );
        CloseHandle( hKeyFile );
      }
      else
        puts( "Не удается открыть файл с публичным ключем\n" );
      CloseHandle( hOutFile );
    }
    else
      puts("Не удается открыть выходной файл\n");
    CloseHandle(hInFile);
  }
  else
    puts( "Не удается открыть входной файл\n" );
  CryptReleaseContext( hProv, 0);
}

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

  if( CryptGenKey( hProv, AT_KEYEXCHANGE, 1024<<16 | CRYPT_EXPORTABLE, &hKey) ) //генерируем 1024-битный ключ для обмена
  {
    struct RSAPubKey1024 key;
    DWORD dwLen = sizeof(struct RSAPubKey1024);
    if( CryptExportKey( hKey, NULL, PUBLICKEYBLOB, 0, (BYTE*) &key, &dwLen) ) //экспортируем ключ
    {
      HANDLE hFile;
      if( (hFile = CreateFileA( "key_pub.rsa", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE )
      {
        if( !WriteFile( hFile, &key, dwLen, &dwLen, NULL) ) //сохраняем файл
          puts( "Не удается сохранить публичный ключ RSA для обмена в файл\n" );
        CloseHandle( hFile );
      }
    }

    struct RSAPrivKey1024 pkey;
    dwLen = sizeof(struct RSAPrivKey1024);
    if( CryptExportKey( hKey, NULL, PRIVATEKEYBLOB, 0, (BYTE*) &key, &dwLen) ) //экспортируем приватный ключ
    {
      HANDLE hFile;
      if( (hFile = CreateFileA( "key_prv.rsa", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE )
      {
        if( !WriteFile( hFile, &key, dwLen, &dwLen, NULL) ) //сохраняем файл
          puts( "Не удается сохранить приватный ключ RSA для обмена в файл\n" );
        CloseHandle( hFile );
      }
    }


    CryptDestroyKey(hKey);
  }
  else
    puts( "Не удается создать ключ RSA для обмена\n" );
  CryptReleaseContext( hProv, 0);
}

int main()
{
  GenerateKey();
  ProcessFile("in.bin", "out.bin", "key_pub.rsa", 'e');
  ProcessFile("out.bin", "out_d.bin", "key_prv.rsa", 'd');
  ExitProcess(0);
  return 0;
}



PM MAIL   Вверх
feodorv
Дата 9.2.2012, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(tofreesky @  9.2.2012,  20:26 Найти цитируемый пост)
Так в чем смысл, это получается симметричное шифрование, а не асимметричность, раз можно зашифровать и расшифровать одним ключом. 

Сам файл шифруется симметричным сессионным ключом, который должен быть ещё передан вместе с зашифрованным файлом, чтобы его ещё можно было расшифровать.
А вот уже сессионный ключ шифруется открытым (несимметричным) пользовательским ключом и дешифруется закрытым пользовательским.

Такая схема совершенно обычна в современной криптографии. Если Вы начнёте закрытым ключом шифровать всё подряд (чтобы послать данные владельцу открытого), то опытный криптолог в конце концов сможет вычислить Ваш закрытый ключ, имея на руках множество данных. В то же время, сессионный ключ короткий (256 байт), почти случайный, существует короткое время - на сессию (то есть не повторяется), фиг выявишь какие-то закономерности в паре закрытый/открытый ключ smile 


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


Бывалый
*


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

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



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


Эксперт
****


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

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



Хотя ошибку нашёл (в экспорте):
Код

WriteFile( hFile, &key, dwLen, &dwLen, NULL)


а нужно:
Код

!WriteFile( hFile, key, dwLen, &dwLen, NULL)


Что уж там выводилось, одному Богу известно)))
Экспорт и импорт работают. Осталось проверить шифрование.

Добавлено через 12 минут и 30 секунд
Цитата(tofreesky @  11.2.2012,  00:26 Найти цитируемый пост)
А экспорт публичного ключа и импорт его и использование, все как в старом коде? 


На своём (домашнем) компьютере выполняется "экспорт.exe", получается файл с именем mykey.rsa.
На (любом) удалённом компьютере выполняется "импорт.exe" (с прилагающимся файлом mykey.rsa). И на домашнем, тоже, так как имена контейнеров я сделал разными)))
Больше ничего в плане генерации ключей делать не нужно. Ключевая пара импортируется в контейнер с именем Movable2 (можно поменять в коде).

Далее берутся исходники отсюда, заменяется NULL в вызовах CryptAcquireContext на "Movable2", компиляться только encrypt.exe и decrypt.exe, которыми Вы как раз шифруете и дешифруете файлы. Для постороннего человека надо написать свою утилиту экспорта только публичного ключа и шифрования им. В любом случае логику задачи нужно проработать, чтобы не запутаться, кто, что и чем шифрует))) А сама задача вполне решаема средствами CryptoAPI.


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


Эксперт
****


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

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



Итак: задача естественным образом разделяется на 2 части - "для себя" и "для других".

Для себя:
  • genkey.exe - программа, генерирующая ключи и сохраняющая их в двух файлах: privkey.rsa (открытый + закрытый ключи) и pubkey.rsa (только открытый ключ); программа выполняется только один раз (если нет необходимости менять ключи)
  • decode.exe - программа расшифровки файлов, пользующаяся privkey.rsa

Для других:
  • encode.exe - программа зашифровки файлов, пользующаяся pubkey.rsa

Все названия условны. Примеры кода, реализующие каждую из этих программ, у Вас есть.
При модификации примерного кода в рабочий нужно учесть 3-а момента:
  • за собой необходимо прибраться. То есть после расшифровки файла вытереть используемые ключи/контейнер ключей, так как CryptImportKey импортирует ключи именно в контейнер ключей.
  • при расшифровке файла имя контейнера стоит генерить случайным образом, то есть что-то вроде UuidCreate/UuidToStringA
  • при зашифровке файла стоит пользоваться фиксированным именем контейнера ключей, который можно и не удалять

Как-то так)))


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


Новичок



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

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



Здравствуйте!!! Я только начинаю разбираться.

Если тупо сменить во всём коде 1024 на 2048 то получим 2048 bit - ключ?

При компиляции вылезли такие варнинги:

1>RSADEMO.CPP(77): warning C4293: <<: отрицательное или слишком большое смещение; поведение не определено

unsigned __int64 fSize = (dwSzHigh << 32) + dwSzLow;

2>RSADEMO.CPP(142): warning C4293: <<: отрицательное или слишком большое смещение; поведение не определено

fEncSize = (dwSzHigh << 32) + dwSzLow - sizeof(EncFileHeader) - 1024/8; //размер зашифрованных данных



Спасибо за внимание!!! 

P.S. Прошу не пинать сильно, а по возможности подсказать как из данных сорцев сделать 2048 и критичны ли варнинги\как их устарнить?

PM MAIL   Вверх
xvr
Дата 3.7.2012, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(darklight131080 @  3.7.2012,  12:56 Найти цитируемый пост)
Если тупо сменить во всём коде 1024 на 2048 то получим 2048 bit - ключ?

Вынужден вас огорчить - тут шифрование выполняется даже не с 1024 битным ключом, а гораздо более коротким  smile 
PM MAIL   Вверх
darklight131080
  Дата 3.7.2012, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Кто может помочь модифицировать до 2048 bit?
Цена вопроса? smile 

Это сообщение отредактировал(а) darklight131080 - 3.7.2012, 16:24
PM MAIL   Вверх
feodorv
Дата 9.7.2012, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(darklight131080 @  3.7.2012,  13:56 Найти цитируемый пост)
Прошу не пинать сильно, а по возможности подсказать как из данных сорцев сделать 2048 

Какой именно ключ Вы хотите сделать 2048-битным: симметричный или несимметричный?

Цитата(darklight131080 @  3.7.2012,  13:56 Найти цитируемый пост)
критичны ли варнинги\как их устарнить?

Критичны. Устраняются так:
Код

unsigned __int64 fSize = ((unsigned __int64) dwSzHigh << 32) + dwSzLow;



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


Бывалый
*


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

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



И как все же экспортировать пару ключей?
PM MAIL   Вверх
tofreesky
Дата 16.8.2012, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



???????
PM MAIL   Вверх
feodorv
Дата 16.8.2012, 23:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(tofreesky @  16.8.2012,  15:21 Найти цитируемый пост)
??????? 

Все коды даны. Все соображения высказаны.
Вам остаётся только немного поэкспериментировать и довести задуманное до конца. smile 


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


Бывалый
*


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

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



del 

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

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

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

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

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


 




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


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

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