Модераторы: 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   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

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

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

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

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


 




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


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

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