Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.145.10.49] |
|
Сообщ.
#1
,
|
|
|
Привет.
Сейчас я пытаюсь написать программу, которая будет шифровать и дешифровать текстовые данные используя алгоритм RSA и вшитые в код закрытый и открытый ключи. Ключи я генерирую через openssl. Вот попытался набросать программу которая будет шифровать текст. Сперва я преобразовываю закрытый ключ в форму с которой может работать Crypto API а затем пытаюсь выполнить шифрование. #include "stdafx.h" #include <string> #include <iostream> #include <windows.h> #include <Wincrypt.h> using namespace std; #pragma comment (lib, "Crypt32.lib") string str_data = "1234567890ABCDEFGH"; const char* szPemPrivKey = "-----BEGIN RSA PRIVATE KEY-----" "MIICWwIBAAKBgQCn7fL/1qsWkJkUtXKZIJNqYfnVByVhK/LzQecPhVR7r+4ng1nZ" "Bxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39uEGeoiYqWl5BLM8pfRAGqzxb" "h600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8EZl2BHKvpDR80GYFlrQIDAQAB" "AoGAZ4ZHsfTTEFwgIyYg+cmdV44DCJMZNihz5AcSvPzDMmUo+m79as/23MnhQGmZ" "TuC28JqBWQVH4OqM2CGf1doEkuLZ/rcgxDipRqbLkEW3T/q+kJ2m9A652ePbHUKX" "ayozDQrWtL4wkvAQQ9Il6vx+AJUzT41hv1PKZ5KWxONiJDkCQQDRsObUVVc6exb+" "YUWVgN0pivHudKIwGUN3js09MjHoen9LbUcvupO3seAUhnNQ17t+1XxsrnPKabQQ" "OimcPK3XAkEAzQQEI++NdoLYJv1oKYADzOUbDAmfoZ/szN6z//53h8zt5ni+6Q0n" "k7nyrVXWuLeP0rEvD0hMOzI0mfUMwbtwGwJAMUYId8y1+qAB/zSMTV1CmwhzYT02" "/2ZwXB/KSp8I60AduXOsTqLhI0FBDpGpd026WUuBOWik/ONp1IZWUMhRcQJAHI+U" "rBTxVjNAPZ5L5owo+2BndjPZA0EuUhQsa1td95M7CUKFBh6JBvF+t1sgALfB145L" "igt+YzjJTzFuR4b/RQJATgZuFyBiuLHrMES2vAtmLRlF6uTzsrNZLLUko2Rfzkzh" "qR4inQOWWZLFzjqp3ha9rzCSVY+nBw+xD+B9hBlsNw==" "-----END RSA PRIVATE KEY-----"; int _tmain(int argc, _TCHAR* argv[]) { DWORD dwBufferLen = 0, cbKeyBlob = 0, cbSignature = 0,i; LPBYTE pbBuffer = NULL, pbKeyBlob = NULL, pbSignature = NULL; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHash = NULL; if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return -1; } pbBuffer = (LPBYTE) LocalAlloc(0, dwBufferLen); if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, pbBuffer, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return -1; } if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, NULL, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return -1; } pbKeyBlob = (LPBYTE) LocalAlloc(0, cbKeyBlob); if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, pbKeyBlob, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return -1; } // Create a temporary and volatile CSP context in order to import // the key and use for signing if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; return -1; } if (!CryptImportKey(hProv, pbKeyBlob, cbKeyBlob, NULL, 0, &hKey)) { cout << "CryptImportKey() failed with error " << GetLastError() << endl; return -1; } // Ctypt string data unsigned long length = str_data.length() + 1; unsigned char * cipherBlock = (unsigned char*)malloc(length); memset(cipherBlock, 0, length); memcpy(cipherBlock, str_data.c_str(), length - 1); if (!CryptEncrypt(hKey, 0, TRUE, 0, cipherBlock, &length, length)) { cout << "CryptEncrypt() failed with error " << GetLastError() << endl; return -1; } cout << cipherBlock << endl; if (pbBuffer) LocalFree(pbBuffer); if (pbKeyBlob) LocalFree(pbKeyBlob); if (pbSignature) LocalFree(pbSignature); if (hHash) CryptDestroyHash(hHash); if (hKey) CryptDestroyKey(hKey); if (hProv) CryptReleaseContext(hProv, 0); return 0; } Программа вылетает на функции CryptEncrypt() с кодом 234, то есть ERROR_MORE_DATA. Хотя, размера буфера (str_data.length() + 1), по идее, должно быть достаточно. Помогите разобраться. |
Сообщ.
#2
,
|
|
|
Немоного подправил программу
#include "stdafx.h" #include <string> #include <iostream> #include <windows.h> #include <Wincrypt.h> using namespace std; #pragma comment (lib, "Crypt32.lib") string str_data = "1234567890ABCDEFGH"; const char* szPemPrivKey = "-----BEGIN RSA PRIVATE KEY-----" "MIICWwIBAAKBgQCn7fL/1qsWkJkUtXKZIJNqYfnVByVhK/LzQecPhVR7r+4ng1nZ" "Bxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39uEGeoiYqWl5BLM8pfRAGqzxb" "h600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8EZl2BHKvpDR80GYFlrQIDAQAB" "AoGAZ4ZHsfTTEFwgIyYg+cmdV44DCJMZNihz5AcSvPzDMmUo+m79as/23MnhQGmZ" "TuC28JqBWQVH4OqM2CGf1doEkuLZ/rcgxDipRqbLkEW3T/q+kJ2m9A652ePbHUKX" "ayozDQrWtL4wkvAQQ9Il6vx+AJUzT41hv1PKZ5KWxONiJDkCQQDRsObUVVc6exb+" "YUWVgN0pivHudKIwGUN3js09MjHoen9LbUcvupO3seAUhnNQ17t+1XxsrnPKabQQ" "OimcPK3XAkEAzQQEI++NdoLYJv1oKYADzOUbDAmfoZ/szN6z//53h8zt5ni+6Q0n" "k7nyrVXWuLeP0rEvD0hMOzI0mfUMwbtwGwJAMUYId8y1+qAB/zSMTV1CmwhzYT02" "/2ZwXB/KSp8I60AduXOsTqLhI0FBDpGpd026WUuBOWik/ONp1IZWUMhRcQJAHI+U" "rBTxVjNAPZ5L5owo+2BndjPZA0EuUhQsa1td95M7CUKFBh6JBvF+t1sgALfB145L" "igt+YzjJTzFuR4b/RQJATgZuFyBiuLHrMES2vAtmLRlF6uTzsrNZLLUko2Rfzkzh" "qR4inQOWWZLFzjqp3ha9rzCSVY+nBw+xD+B9hBlsNw==" "-----END RSA PRIVATE KEY-----"; int _tmain(int argc, _TCHAR* argv[]) { DWORD dwBufferLen = 0, cbKeyBlob = 0, cbSignature = 0,i; LPBYTE pbBuffer = NULL, pbKeyBlob = NULL, pbSignature = NULL; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHash = NULL; DWORD dwResult; if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return -1; } pbBuffer = (LPBYTE) LocalAlloc(0, dwBufferLen); if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, pbBuffer, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return -1; } if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, NULL, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return -1; } pbKeyBlob = (LPBYTE) LocalAlloc(0, cbKeyBlob); if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, pbKeyBlob, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return -1; } // Create a temporary and volatile CSP context in order to import // the key and use for signing //if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) //{ // cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; // return -1; //} if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)) { dwResult = GetLastError(); if (dwResult == NTE_BAD_KEYSET) { if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; return -1; } } else { cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; return -1; } } if (!CryptImportKey(hProv, pbKeyBlob, cbKeyBlob, NULL, 0, &hKey)) { cout << "CryptImportKey() failed with error " << GetLastError() << endl; return -1; } // Get buffer length DWORD bufLen = 0; DWORD strLen = str_data.length() * sizeof(char); if (!CryptEncrypt(hKey, 0, true, 0, 0, &bufLen, strLen)) { cout << "CryptEncrypt() failed with error " << GetLastError() << endl; return -1; } // Crypt string data BYTE *cipherBlock= new BYTE[bufLen]; memset((void *)cipherBlock, 0, bufLen); memcpy((void *)cipherBlock, str_data.c_str(), strLen); if (!CryptEncrypt(hKey, 0, TRUE, 0, cipherBlock, &bufLen, strLen)) { cout << "CryptEncrypt() failed with error " << GetLastError() << endl; // NTE_BAD_LEN return -1; } cout << cipherBlock << endl; if (pbBuffer) LocalFree(pbBuffer); if (pbKeyBlob) LocalFree(pbKeyBlob); if (pbSignature) LocalFree(pbSignature); if (hHash) CryptDestroyHash(hHash); if (hKey) CryptDestroyKey(hKey); if (hProv) CryptReleaseContext(hProv, 0); return 0; } Теперь 2й вызов CryptEncrypt() вызывает ошибку NTE_BAD_LEN. Я новичок в этом деле. Серьезно, нужно помощь ) |
Сообщ.
#3
,
|
|
|
// Get buffer length DWORD strLen = str_data.length() * sizeof(char); DWORD bufLen = strLen; //<----- !!! if (!CryptEncrypt(hKey, 0, true, 0, 0, &bufLen, bufLen)) { ... } // Crypt string data ... if (!CryptEncrypt(hKey, 0, TRUE, 0, cipherBlock, &strLen, bufLen)) //<----- !!! { ... } strLen - реальный размер данных, bufLen - размер буфера >= strLen |
Сообщ.
#4
,
|
|
|
Понял.
Теперь попытался сделать дешифрование и снова не смог понять что не так. Шифрование и дешифрование теперь вынесены в функции Crypt() и Decrypt(). При дешифровании CryptDecrypt() вылетает с ошибкой NTE_NO_KEY, хотя параметр hKey под отладчиком вовсе не пустой. #include "stdafx.h" #include <string> #include <iostream> #include <windows.h> #include <Wincrypt.h> using namespace std; #pragma comment (lib, "Crypt32.lib") string Decrypt (const string& _cryptedStr); string Crypt (const string& _str); const char* szPemPrivKey = "-----BEGIN RSA PRIVATE KEY-----" "MIICWwIBAAKBgQCn7fL/1qsWkJkUtXKZIJNqYfnVByVhK/LzQecPhVR7r+4ng1nZ" "Bxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39uEGeoiYqWl5BLM8pfRAGqzxb" "h600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8EZl2BHKvpDR80GYFlrQIDAQAB" "AoGAZ4ZHsfTTEFwgIyYg+cmdV44DCJMZNihz5AcSvPzDMmUo+m79as/23MnhQGmZ" "TuC28JqBWQVH4OqM2CGf1doEkuLZ/rcgxDipRqbLkEW3T/q+kJ2m9A652ePbHUKX" "ayozDQrWtL4wkvAQQ9Il6vx+AJUzT41hv1PKZ5KWxONiJDkCQQDRsObUVVc6exb+" "YUWVgN0pivHudKIwGUN3js09MjHoen9LbUcvupO3seAUhnNQ17t+1XxsrnPKabQQ" "OimcPK3XAkEAzQQEI++NdoLYJv1oKYADzOUbDAmfoZ/szN6z//53h8zt5ni+6Q0n" "k7nyrVXWuLeP0rEvD0hMOzI0mfUMwbtwGwJAMUYId8y1+qAB/zSMTV1CmwhzYT02" "/2ZwXB/KSp8I60AduXOsTqLhI0FBDpGpd026WUuBOWik/ONp1IZWUMhRcQJAHI+U" "rBTxVjNAPZ5L5owo+2BndjPZA0EuUhQsa1td95M7CUKFBh6JBvF+t1sgALfB145L" "igt+YzjJTzFuR4b/RQJATgZuFyBiuLHrMES2vAtmLRlF6uTzsrNZLLUko2Rfzkzh" "qR4inQOWWZLFzjqp3ha9rzCSVY+nBw+xD+B9hBlsNw==" "-----END RSA PRIVATE KEY-----"; const char* szPemPublicKey = "-----BEGIN PUBLIC KEY-----" "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn7fL/1qsWkJkUtXKZIJNqYfnV" "ByVhK/LzQecPhVR7r+4ng1nZBxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39" "uEGeoiYqWl5BLM8pfRAGqzxbh600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8E" "Zl2BHKvpDR80GYFlrQIDAQAB" "-----END PUBLIC KEY-----"; int _tmain(int argc, _TCHAR* argv[]) { string str_data = "1234567890ABCDEFGH"; string encrytedStr = Crypt(str_data); cout << encrytedStr << endl; string decryptedStr = Decrypt(encrytedStr); cout << decryptedStr << endl; return 0; } string Crypt(const string& _str) { DWORD dwBufferLen = 0, cbKeyBlob = 0, cbSignature = 0/*,i*/; LPBYTE pbBuffer = NULL, pbKeyBlob = NULL, pbSignature = NULL; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHash = NULL; if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return ""; } pbBuffer = (LPBYTE) LocalAlloc(0, dwBufferLen); if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, pbBuffer, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return ""; } if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, NULL, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return ""; } pbKeyBlob = (LPBYTE) LocalAlloc(0, cbKeyBlob); if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, pbKeyBlob, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return ""; } if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)) { if (GetLastError() == NTE_BAD_KEYSET) { if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; return ""; } } else { cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; return ""; } } if (!CryptImportKey(hProv, pbKeyBlob, cbKeyBlob, NULL, 0, &hKey)) { cout << "CryptImportKey() failed with error " << GetLastError() << endl; return ""; } // get size of buffer DWORD strLen = _str.length() * sizeof(char); DWORD bufLen = strLen; if (!CryptEncrypt(hKey, 0, true, 0, 0, &bufLen, strLen)) { cout << "CryptEncrypt() failed with error " << GetLastError() << endl; return ""; } // Crypt string data BYTE *cipherBlock= new BYTE[bufLen]; memset((void *)cipherBlock, 0, bufLen); memcpy((void *)cipherBlock, _str.c_str(), strLen); if (!CryptEncrypt(hKey, 0, TRUE, 0, cipherBlock, &strLen, bufLen)) { cout << "CryptEncrypt() failed with error " << GetLastError() << endl; return ""; } //cout << cipherBlock << endl << endl; if (pbBuffer) LocalFree(pbBuffer); if (pbKeyBlob) LocalFree(pbKeyBlob); if (pbSignature) LocalFree(pbSignature); if (hHash) CryptDestroyHash(hHash); if (hKey) CryptDestroyKey(hKey); if (hProv) CryptReleaseContext(hProv, 0); std::string s(reinterpret_cast<char const*>(cipherBlock)); return s; } string Decrypt(const string& _cryptedStr) { char pemPubKey[2048]; memcpy((void *)pemPubKey, szPemPublicKey, strlen(szPemPublicKey)); char derPubKey[2048]; DWORD derPubKeyLen = 2048; CERT_PUBLIC_KEY_INFO *publicKeyInfo; DWORD publicKeyInfoLen; HANDLE hFile; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; // Convert from PEM format to DER format - removes header and footer and decodes from base64 if ( !CryptStringToBinaryA( pemPubKey, 0, CRYPT_STRING_BASE64HEADER, (BYTE*)derPubKey, &derPubKeyLen, NULL, NULL ) ) { fprintf( stderr, "CryptStringToBinary failed. Err: %d\n", GetLastError() ); return ""; } // Decode from DER format to CERT_PUBLIC_KEY_INFO if ( !CryptDecodeObjectEx( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, (BYTE*)derPubKey, derPubKeyLen, CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen ) ) { fprintf( stderr, "CryptDecodeObjectEx 1 failed. Err: %p\n", GetLastError() ); return ""; } if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) ) { { printf( "CryptAcquireContext failed - err=0x%x.\n", GetLastError() ); return ""; } } if ( !CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey ) ) { fprintf( stderr, "CryptImportPublicKeyInfo failed. error: %d\n", GetLastError() ); return ""; } // LocalFree( publicKeyInfo ); // Decrypt DWORD strLen = _cryptedStr.length(); DWORD bufLen = strLen + 1; BYTE* cipherBlock= new BYTE[bufLen]; memset((void *)cipherBlock, 0, bufLen); memcpy((void *)cipherBlock, _cryptedStr.c_str(), strLen); if (!CryptDecrypt(hKey, 0, TRUE, 0, cipherBlock, &strLen)) { cout << "CryptDecrypt() failed with error " << GetLastError() << endl; // NTE_NO_KEY // Key does not exist. return ""; } std::string s(reinterpret_cast<char const*>(cipherBlock)); return s; return 0; } |
Сообщ.
#5
,
|
|
|
Цитата CantStop0708 @ При дешифровании CryptDecrypt() вылетает с ошибкой NTE_NO_KEY, хотя параметр hKey под отладчиком вовсе не пустой. RSA - асимметричный алгоритм, в котором для шифрования используется публичный ключ, а для дешифрования - приватный, а не наоборот, как у тебя. Цитата CantStop0708 @ Ты не думаешь, что при таком копировании бинарных данных в строку происходит обрезка их длины по первому нулевому байту? Нужно либо возвращать данные as is как массив BYTE*, либо кодировать их в строку BASE64 или HEX. К тому же после преобразования\копирования в строку исходный cipherBlock нужно удалить string Crypt(const string& _str) {... std::string s(reinterpret_cast<char const*>(cipherBlock)); return s; } |
Сообщ.
#6
,
|
|
|
Исправил. Теперь шифруем публичным ключом и дешифруем приватным. Возвращаем данные as is как массив BYTE*.
При дешифровании считываем длинну дешифрованной строки, которая в общем-то правильно определяется, но при выводе почему-то в конец строки дописывается 4 лишних символа. То есть, если изначально строка была 1234567890ABCDEFGH, то при выводе имеем 1234567890ABCDEFGH**** #include "stdafx.h" #include <string> #include <iostream> #include <windows.h> #include <Wincrypt.h> using namespace std; #pragma comment (lib, "Crypt32.lib") // |_str| - string to encrypt // |_outLength| - length of output data BYTE* Crypt (const string& _str, DWORD* _outLength); // |_encryptedData| - data to decrypt // |_length| - length of |_encryptedData| (will change to the length of decrypted data) BYTE* Decrypt (BYTE* _encryptedData, DWORD* _length); const char* szPemPrivKey = "-----BEGIN RSA PRIVATE KEY-----" "MIICWwIBAAKBgQCn7fL/1qsWkJkUtXKZIJNqYfnVByVhK/LzQecPhVR7r+4ng1nZ" "Bxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39uEGeoiYqWl5BLM8pfRAGqzxb" "h600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8EZl2BHKvpDR80GYFlrQIDAQAB" "AoGAZ4ZHsfTTEFwgIyYg+cmdV44DCJMZNihz5AcSvPzDMmUo+m79as/23MnhQGmZ" "TuC28JqBWQVH4OqM2CGf1doEkuLZ/rcgxDipRqbLkEW3T/q+kJ2m9A652ePbHUKX" "ayozDQrWtL4wkvAQQ9Il6vx+AJUzT41hv1PKZ5KWxONiJDkCQQDRsObUVVc6exb+" "YUWVgN0pivHudKIwGUN3js09MjHoen9LbUcvupO3seAUhnNQ17t+1XxsrnPKabQQ" "OimcPK3XAkEAzQQEI++NdoLYJv1oKYADzOUbDAmfoZ/szN6z//53h8zt5ni+6Q0n" "k7nyrVXWuLeP0rEvD0hMOzI0mfUMwbtwGwJAMUYId8y1+qAB/zSMTV1CmwhzYT02" "/2ZwXB/KSp8I60AduXOsTqLhI0FBDpGpd026WUuBOWik/ONp1IZWUMhRcQJAHI+U" "rBTxVjNAPZ5L5owo+2BndjPZA0EuUhQsa1td95M7CUKFBh6JBvF+t1sgALfB145L" "igt+YzjJTzFuR4b/RQJATgZuFyBiuLHrMES2vAtmLRlF6uTzsrNZLLUko2Rfzkzh" "qR4inQOWWZLFzjqp3ha9rzCSVY+nBw+xD+B9hBlsNw==" "-----END RSA PRIVATE KEY-----"; const char* szPemPublicKey = "-----BEGIN PUBLIC KEY-----" "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn7fL/1qsWkJkUtXKZIJNqYfnV" "ByVhK/LzQecPhVR7r+4ng1nZBxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39" "uEGeoiYqWl5BLM8pfRAGqzxbh600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8E" "Zl2BHKvpDR80GYFlrQIDAQAB" "-----END PUBLIC KEY-----"; int _tmain(int argc, _TCHAR* argv[]) { string str_data = "1234567890ABCDEFGH"; DWORD encryptedDataLen; BYTE* encrytedData = Crypt(str_data, &encryptedDataLen); cout << encrytedData << endl; cout << endl; BYTE* decryptedData = Decrypt(encrytedData, &encryptedDataLen); cout << decryptedData << endl; delete(encrytedData); delete(decryptedData); return 0; } // |_str| - string to encrypt // |_outLength| - length of output data BYTE* Crypt(const string& _str, DWORD* _outLength) { char pemPubKey[2048]; memcpy((void *)pemPubKey, szPemPublicKey, strlen(szPemPublicKey)); char derPubKey[2048]; DWORD derPubKeyLen = 2048; CERT_PUBLIC_KEY_INFO *publicKeyInfo; DWORD publicKeyInfoLen; HANDLE hFile; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; // Convert from PEM format to DER format - removes header and footer and decodes from base64 if ( !CryptStringToBinaryA( pemPubKey, 0, CRYPT_STRING_BASE64HEADER, (BYTE*)derPubKey, &derPubKeyLen, NULL, NULL ) ) { fprintf( stderr, "CryptStringToBinary failed. Err: %d\n", GetLastError() ); return NULL; } // Decode from DER format to CERT_PUBLIC_KEY_INFO if ( !CryptDecodeObjectEx( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, (BYTE*)derPubKey, derPubKeyLen, CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen ) ) { fprintf( stderr, "CryptDecodeObjectEx 1 failed. Err: %p\n", GetLastError() ); return NULL; } if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) ) { { printf( "CryptAcquireContext failed - err=0x%x.\n", GetLastError() ); return NULL; } } if ( !CryptImportPublicKeyInfo( hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey ) ) { fprintf( stderr, "CryptImportPublicKeyInfo failed. error: %d\n", GetLastError() ); return NULL; } // LocalFree( publicKeyInfo ); // get size of buffer DWORD strLen = _str.length() * sizeof(char); DWORD bufLen = strLen; if (!CryptEncrypt(hKey, 0, true, 0, 0, &bufLen, strLen)) { cout << "CryptEncrypt() failed with error " << GetLastError() << endl; return NULL; } // Crypt string data BYTE *cipherBlock= new BYTE[bufLen]; memset((void *)cipherBlock, 0, bufLen); memcpy((void *)cipherBlock, _str.c_str(), strLen); if (!CryptEncrypt(hKey, 0, TRUE, 0, cipherBlock, &strLen, bufLen)) { cout << "CryptEncrypt() failed with error " << GetLastError() << endl; return NULL; } *_outLength = bufLen; return cipherBlock; } // |_encryptedData| - data to decrypt // |_length| - length of |_encryptedData| (will change to the length of decrypted data) BYTE* Decrypt(BYTE* _encryptedData, DWORD* _length) { DWORD dwBufferLen = 0, cbKeyBlob = 0, cbSignature = 0/*,i*/; LPBYTE pbBuffer = NULL, pbKeyBlob = NULL, pbSignature = NULL; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; HCRYPTHASH hHash = NULL; if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return NULL; } pbBuffer = (LPBYTE) LocalAlloc(0, dwBufferLen); if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, pbBuffer, &dwBufferLen, NULL, NULL)) { cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl; return NULL; } if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, NULL, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return NULL; } pbKeyBlob = (LPBYTE) LocalAlloc(0, cbKeyBlob); if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, pbKeyBlob, &cbKeyBlob)) { cout << "Failed to parse private key. Error " << GetLastError() << endl; return NULL; } if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)) { if (GetLastError() == NTE_BAD_KEYSET) { if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; return NULL; } } else { cout << "CryptAcquireContext() failed with error " << GetLastError() << endl; return NULL; } } if (!CryptImportKey(hProv, pbKeyBlob, cbKeyBlob, NULL, 0, &hKey)) { cout << "CryptImportKey() failed with error " << GetLastError() << endl; return NULL; } // Decrypt DWORD bufLen = *_length + 1; BYTE* cipherBlock= new BYTE[bufLen]; memset((void *)cipherBlock, 0, bufLen); memcpy((void *)cipherBlock, _encryptedData, *_length); if (!CryptDecrypt(hKey, 0, TRUE, 0, cipherBlock, _length)) { cout << "CryptDecrypt() failed with error " << GetLastError() << endl; return NULL; } // Decrypted data BYTE* decryptedData = new BYTE[*_length]; memset((void *)decryptedData, 0, *_length); memcpy((void *)decryptedData, cipherBlock, *_length); delete(cipherBlock); if (pbBuffer) LocalFree(pbBuffer); if (pbKeyBlob) LocalFree(pbKeyBlob); if (pbSignature) LocalFree(pbSignature); if (hHash) CryptDestroyHash(hHash); if (hKey) CryptDestroyKey(hKey); if (hProv) CryptReleaseContext(hProv, 0); return decryptedData; } |
Сообщ.
#7
,
|
|
|
Цитата CantStop0708 @ При дешифровании считываем длинну дешифрованной строки, которая в общем-то правильно определяется, но при выводе почему-то в конец строки дописывается 4 лишних символа. Попробуй так: //... //... // Decrypted data BYTE* decryptedData = new BYTE[*_length+1]; decryptedData[*_length]=0; memcpy((void *)decryptedData, cipherBlock, *_length); //... //... Или: //... BYTE* decryptedData = Decrypt(encrytedData, &encryptedDataLen); for(DWORD i=0;i<encryptedDataLen;++i) { cout << decryptedData[i];} cout << endl; // cout << decryptedData << endl; //... |
Сообщ.
#8
,
|
|
|
CantStop0708
В CryptAcquireContext в качестве провайдера нужно указывать MS_ENHANCED_PROV |
Сообщ.
#9
,
|
|
|
Цитата ЫукпШ @ Попробуй так: //... //... // Decrypted data BYTE* decryptedData = new BYTE[*_length+1]; decryptedData[*_length]=0; memcpy((void *)decryptedData, cipherBlock, *_length); //... //... Да, это помогло. Цитата leo В CryptAcquireContext в качестве провайдера нужно указывать MS_ENHANCED_PROV А почему именно так? У меня так же есть еще один вопрос. Насколько я понимаю, Crypto API - платформенно зависимое. То есть то, что было зашифровано под Win XP не факт что расшифруется под Win 7, например. Но до этого я думал что RSA и в Африке RSA. А так получается что RSA RSA рознь. Но что если я хочу шифровать на C++, а расшифровывать на каком-нибудь PHP? Тогда выходит, что использовать Crypto API вообще не вариант? И можно ли тогда вообще использовать готовые библиотеки, раз такое дело, или только вручную кодировать алгоритм чтобы быть уверенным что он работает одинаково? |
Сообщ.
#10
,
|
|
|
Цитата CantStop0708 @ А почему именно так? См.последнее примечание к CryptEncrypt\Decrypt Цитата CantStop0708 @ Но до этого я думал что RSA и в Африке RSA. А так получается что RSA RSA рознь. RSA - это общее название метода\алгоритма асимметричного шифрования, а его конкретные реализации (представления ключей, разбивки данных на блоки, выравнивания длины, формата выходных данных с учетом служебных полей и т.п.) определяются стандартами PKCS (Public Key Cryptography Standards). Поэтому, если Crypt\Encrypt выполняются по одному стандарту (с учетом big\little-endian записи данных), то проблем быть не должно Цитата CantStop0708 @ То есть то, что было зашифровано под Win XP не факт что расшифруется под Win 7, например. Ну если на шару задавать разных провайдеров для Crypt\Encrypt (как у тебя - NULL и MS_DEF_PROV), разные флаги и т.п., то не исключено |
Сообщ.
#11
,
|
|
|
Всем благодарности за помощь.
|
Сообщ.
#12
,
|
|
|
Целый вирус шифровальщик получается
|
Сообщ.
#13
,
|
|
|
Привет всем.
Вопрос не совсем по теме, но близок, поэтому спрошу здесь. --- Пытаюсь использовать CryptoAPI (Windows), RSA асимметричным алгоритмом. Вроде-бы всё получается - ключи создаются, сообщение шифруется/дешифруется, всё хорошо. Однако обнаружен странный эффект - если произвести де-шифрование на той-же машине, где создавались ключи - тогда для де-шифрования можно использовать публичный ключ. --- Если передать публичный ключ на другую машину физически, тогда всё получается как надо. Зашифровать можно, расшифровать - нет. На машине, где генерировались ключи, для де-шифрования подходит любой из них. Значит, приватный ключ вообще не нужен ? --- Это какая-то ошибка или я что-то не правильно делаю ? |