Консультация № 140966
29.07.2008, 11:45
0.00 руб.
0 0 0
Здравствуйте, уважаемые эксперты! Я хотел написать программу с поддержкой RSA-шифрования, но никак не могу разобраться с CryptoAPI, нашел пример, вроде бы работает замечательно, но похоже автором допущена ошибка, т.к. после шифрования файла открытым ключем, он прекрасно этим же ключем и расшифровывается, хотя должен дешифроваться только закрытым ключем. Так же приватный ключ, почему-то содержит в себе и публичный.
Был бы вам очень благодарен, если бы вы указали ошибку в коде, либо дали ссылку на работающий пример.
В приложении исходник RSA.cpp, линкуется с advapi32.lib (cl RSA.cpp advapi32.lib)

Приложение:
// RSA.cpp : Defines the entry point for the console application.
//
#define _WIN32_WINNT 0x0500
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <tchar.h>

#define KEYLENGTH 512
#define KEYBUFLENGTH 1024
#define DATALENGTH 1024

void PrintError (char *pszBegin, DWORD dwError)
{
LPVOID lpMsgBuf;
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
printf("%s (%u): %s", pszBegin, dwError, (char *)lpMsgBuf);
LocalFree( lpMsgBuf );
}

void CreateKeys();
void EncodeFile();
void DecodeFile();

int _tmain(int argc, _TCHAR* argv[])
{
char szRes[12];
printf ("Choose:
1 - Create keys
2 - Encode file
3 - Decode file
4 - Show error text
h - help
q - to quit
");
while (true) {
printf ("
>");
scanf ("%s", szRes);
if (!strcmp(szRes, "1")) CreateKeys ();
if (!strcmp(szRes, "2")) EncodeFile ();
if (!strcmp(szRes, "3")) DecodeFile ();
if (!strcmp(szRes, "4")) {
printf ("Enter error code: ");
scanf ("%s", szRes);
PrintError ("Error message :", atoi (szRes));
printf ("
");
}
if (!strcmp(szRes, "q") || !strcmp(szRes, "Q")) break;
if (!strcmp(szRes, "h") || !strcmp(szRes, "H"))
printf ("Choose:
1 - Create keys
2 - Encode file
3 - Decode file
4 - Show error text
h - help
q - to quit
");
}
return 0;
}

void CreateKeys()
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hPPKey = NULL;
BOOL bRes;
HANDLE hKeyFile;
char szPrvKeyFile [MAX_PATH];
char szPubKeyFile [MAX_PATH];
char szPubKey [KEYBUFLENGTH];
char szPrvKey [KEYBUFLENGTH];
char szKeyLen [64];
DWORD dwKeyLen;
DWORD dwWriten = 0;
// Generate public/private pair
printf ("Generating private and public keys
");
printf ("Enter public key file name: "); scanf ("%s", szPubKeyFile);
printf ("Enter private key file name: "); scanf ("%s", szPrvKeyFile);
printf ("Key len (512 default): "); scanf ("%s", szKeyLen);
dwKeyLen = atoi (szKeyLen);
if (!dwKeyLen) dwKeyLen = KEYLENGTH;
// 1) Initialize СryptoAPI
bRes = CryptAcquireContext (&hCryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0);
if (bRes) printf ("CryptAcquireContext () ... OK
");
else PrintError ("CryptAcquireContext", GetLastError());
// 2) Create Key
bRes = CryptGenKey (hCryptProv, AT_KEYEXCHANGE, dwKeyLen<<16 | CRYPT_EXPORTABLE, &hPPKey);
if (bRes) printf ("CryptGenKey (private/public) ... OK
");
else PrintError ("CryptGenKey", GetLastError());
// 3) Exporting keys
DWORD dwPubKeyLen = KEYBUFLENGTH;
bRes = CryptExportKey (hPPKey, NULL, PUBLICKEYBLOB, 0, (BYTE *)&szPubKey[0], &dwPubKeyLen);
if (bRes) {
printf ("CryptExportKey (PUBLICKEYBLOB) ... OK
");
hKeyFile = ::CreateFile (szPubKeyFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
::WriteFile (hKeyFile, szPubKey, dwPubKeyLen, &dwWriten, NULL);
if (dwPubKeyLen == dwWriten) printf ("Key saved ... OK
");
::CloseHandle (hKeyFile);
}
else PrintError ("CryptExportKey (PUBLICKEYBLOB)", GetLastError());
DWORD dwPrvKeyLen = KEYBUFLENGTH;
bRes = CryptExportKey (hPPKey, NULL, PRIVATEKEYBLOB, 0, (BYTE *)&szPrvKey[0], &dwPrvKeyLen);
if (bRes) {
printf ("CryptExportKey (PRIVATEKEYBLOB) ... OK
");
// Remove public part from key
CRYPT_DATA_BLOB *pBuf1 = (CRYPT_DATA_BLOB *)&szPrvKey[0];
CRYPT_DATA_BLOB *pBuf2 = (CRYPT_DATA_BLOB *)&szPubKey[0];
char *p1 = (char *)&pBuf1->pbData;
char *p2 = (char *)&pBuf2->pbData;
int n = 0;
DWORD n1 = dwPubKeyLen - sizeof (DWORD);
for (DWORD i=0; i<n1; i++) {
if (!memcmp(p1, p2, 1)) n++; // dwPubKeyLen-sizeof(DWORD)
p1++;
p2++;
}
printf ("Found %i times (%i of %i)
", n, n1, dwPubKeyLen);
// ============================
hKeyFile = ::CreateFile (szPrvKeyFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
::WriteFile (hKeyFile, szPrvKey, dwPrvKeyLen, &dwWriten, NULL);
if (dwPrvKeyLen == dwWriten) printf ("Key saved ... OK
");
::CloseHandle (hKeyFile);
}
else PrintError ("CryptExportKey (PRIVATEKEYBLOB)", GetLastError());
// 4) Destroy key
bRes = CryptDestroyKey (hPPKey);
if (bRes) printf ("CryptDestroyKey () ... OK
");
else PrintError ("CryptDestroyKey", GetLastError());
// 5) Close CryptoAPI
bRes = CryptReleaseContext(hCryptProv, 0);
if (bRes) printf ("CryptReleaseContext () ... OK
");
else PrintError ("CryptReleaseContext ()", GetLastError());
}

void EncodeFile()
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hPPKey = NULL;
HCRYPTKEY hSesKey = NULL;
BOOL bRes;
HANDLE hFile1;
HANDLE hFile2;
char szPubKeyFile [MAX_PATH];
char szFile [MAX_PATH];
char szResFile [MAX_PATH];
char szPubKey [KEYBUFLENGTH];
char szBuf [2*DATALENGTH];
DWORD dwPubKeySize = 0;
DWORD dwRWBytes = 0;
// Encode data
printf ("Encode data
");
printf ("LOAD: Enter public key file name: "); scanf ("%s", szPubKeyFile);
printf ("LOAD: Enter file name to encrypt: "); scanf ("%s", szFile);
printf ("SAVE: Enter file name for result: "); scanf ("%s", szResFile);
// Load pub key
hFile1 = ::CreateFile (szPubKeyFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile1) { printf ("Pub key file IO error
"); return; }
DWORD dwSize = ::GetFileSize (hFile1, NULL);
::ReadFile (hFile1, szPubKey, dwSize, &dwPubKeySize, NULL);
::CloseHandle (hFile1);
if (dwSize != dwPubKeySize) { printf ("Pub key file read error
"); return; }
// 1) Initialize СryptoAPI
bRes = CryptAcquireContext (&hCryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0);
if (bRes) printf ("CryptAcquireContext () ... OK
");
else PrintError ("CryptAcquireContext", GetLastError());
// 3) Import public key
bRes = CryptImportKey (hCryptProv, (BYTE *)&szPubKey[0], dwPubKeySize, NULL, 0, &hPPKey);
if (bRes) printf ("CryptImportKey (public) ... OK
");
else PrintError ("CryptImportKey (public)", GetLastError());
// 5) Enrypt data
hFile1 = ::CreateFile (szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hFile2 = ::CreateFile (szResFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile1 && !hFile2) { printf ("File IO error.
"); return; }
DWORD dwBlockSaved = 0;
DWORD dwBlockTotal = 0;
::ReadFile (hFile1, szBuf, DATALENGTH, &dwRWBytes, NULL);
while (dwRWBytes != 0) {
dwBlockTotal++;
BOOL bFinal = FALSE;
DWORD dwBufLen = dwRWBytes;
if (dwRWBytes != DATALENGTH) bFinal = TRUE;
bRes = CryptEncrypt (hPPKey, 0, bFinal, 0, (BYTE *)&szBuf[0], &dwBufLen, 2*DATALENGTH);
if (!bRes) PrintError ("CryptEncrypt", GetLastError());
// Save block
DWORD dwRWBytes2 = 0;
::WriteFile (hFile2, szBuf, dwBufLen, &dwRWBytes2, NULL);
if (dwRWBytes2 == dwBufLen) dwBlockSaved++;
::ReadFile (hFile1, szBuf, DATALENGTH, &dwRWBytes, NULL);
}
printf ("Total blocks = %u, Saved blocks = %u
", dwBlockTotal, dwBlockSaved);
::CloseHandle (hFile1);
::CloseHandle (hFile2);
// 7) Destroy public key
bRes = CryptDestroyKey (hPPKey);
if (bRes) printf ("CryptDestroyKey (public) ... OK
");
else PrintError ("CryptDestroyKey (public)", GetLastError());
// 8) Close CryptoAPI
bRes = CryptReleaseContext(hCryptProv, 0);
if (bRes) printf ("CryptReleaseContext () ... OK
");
else PrintError ("CryptReleaseContext ()", GetLastError());
// ==========================================================================================================
}

void DecodeFile()
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hPPKey = NULL;
HCRYPTKEY hSesKey = NULL;
BOOL bRes;
HANDLE hFile1;
HANDLE hFile2;
char szPrvKeyFile [MAX_PATH];
char szFile [MAX_PATH];
char szResFile [MAX_PATH];
char szPrvKey [KEYBUFLENGTH];
char szBuf [2*DATALENGTH];
DWORD dwPrvKeySize = 0;
DWORD dwSesKeySize = 0;
DWORD dwRWBytes = 0;
DWORD dwSize = 0;

// Decode data
printf ("Decode data
");
printf ("LOAD: Enter private key file name: "); scanf ("%s", szPrvKeyFile);
printf ("LOAD: Enter file name to decrypt: "); scanf ("%s", szFile);
printf ("SAVE: Enter file name for result: "); scanf ("%s", szResFile);
// Load private key
hFile1 = ::CreateFile (szPrvKeyFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile1) { printf ("Prv key file IO error
"); return; }
dwSize = ::GetFileSize (hFile1, NULL);
::ReadFile (hFile1, szPrvKey, dwSize, &dwPrvKeySize, NULL);
::CloseHandle (hFile1);
if (dwSize != dwPrvKeySize) { printf ("Prv key file read error
"); return; }
// 1) Initialize СryptoAPI
bRes = CryptAcquireContext (&hCryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0);
if (bRes) printf ("CryptAcquireContext () ... OK
");
else PrintError ("CryptAcquireContext", GetLastError());
// 2) Import private key
bRes = CryptImportKey (hCryptProv, (BYTE *)&szPrvKey[0], dwPrvKeySize, NULL, 0, &hPPKey);
if (bRes) printf ("CryptImportKey (private) ... OK
");
else PrintError ("CryptImportKey (private)", GetLastError());
// 5) Decrypt data
hFile1 = ::CreateFile (szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hFile2 = ::CreateFile (szResFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile1 && !hFile2) { printf ("File IO error.
"); return; }
DWORD dwBlockSaved = 0;
DWORD dwBlockTotal = 0;
::ReadFile (hFile1, szBuf, DATALENGTH, &dwRWBytes, NULL);
while (dwRWBytes != 0) {
dwBlockTotal++;
BOOL bFinal = FALSE;
DWORD dwBufLen = dwRWBytes;
if (dwRWBytes != DATALENGTH) bFinal = TRUE;
bRes = CryptDecrypt (hPPKey, 0, bFinal, 0, (BYTE *)&szBuf[0], &dwBufLen);
if (!bRes) PrintError ("CryptEncrypt", GetLastError());
// Save block
DWORD dwRWBytes2 = 0;
::WriteFile (hFile2, szBuf, dwBufLen, &dwRWBytes2, NULL);
if (dwRWBytes2 == dwBufLen) dwBlockSaved++;
::ReadFile (hFile1, szBuf, DATALENGTH, &dwRWBytes, NULL);
}
printf ("Total blocks = %u, Saved blocks = %u
", dwBlockTotal, dwBlockSaved);
::CloseHandle (hFile1);
::CloseHandle (hFile2);
// 7) Destroy private key
bRes = CryptDestroyKey (hPPKey);
if (bRes) printf ("CryptDestroyKey (private) ... OK
");
else PrintError ("CryptDestroyKey (private)", GetLastError());
// 8) Close CryptoAPI
bRes = CryptReleaseContext(hCryptProv, 0);
if (bRes) printf ("CryptReleaseContext () ... OK
");
else PrintError ("CryptReleaseContext ()", GetLastError());
}

Обсуждение

Форма ответа