Здравствуйте. Возникла необходимость криптовать данные используя алгоритм RSA на сервере(с#) и на клиенте(с++). Отдельно в с# и отдельно в с++ криптование работает отлично. Генерю пару ключей в С# и импортирую открытый ключ в с++, криптую, закриптованые данные передаю обратно в с#. И пробую декриптовать, выдает ошибку: "Encryption failed.Bad Data. Подскажите, пожалуйста, в чем может быть проблема? Код с#(код минимальный, без обработки ошибок): Код | RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512/*key size*/); RSAParameters rsaParams = rsa.ExportParameters(false);
Console.WriteLine("RSA Exponent: {0}", toHexStr(rsaParams.Exponent)); Console.WriteLine("RSA PublicKey: {0}", toHexStr(rsaParams.Modulus));
byte[] encryptedData; string sEncHex = Console.ReadLine(); encryptedData = toBytes(sEncHex);
byte[] decryptedData = rsa.Decrypt( encryptedData, false);
|
Код с++(код минимальный, без обработки ошибок): Код | HCRYPTPROV hCryptProv = NULL; CryptAcquireContext(&hCryptProv, A2W("1ContainerName"), MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET);
//RSA Public Key беру сгенеренный из c# char* cPublKeyStr = "DF726C2D8D4D1447C9C6395F4DD96743015DB83D6D5A704D9436D2EDFCDE8105EB8F77E72CC06AAD42769289EE8A5E97A71B2FCD404088C3B17667A96B7C52F7"; BYTE* pModulus = new BYTE[64]; // Byte array that contains the modulus. memset(pModulus, 0, 64); DWORD cbModulus = (DWORD)strlen(cPublKeyStr); // Size of the modulus in bytes. DWORD dwExponent = 0x10001; // RSA Exponent
hexToBA( cPublKeyStr, pModulus, &cbModulus );
DWORD cbKeyBlob = cbModulus + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY); BYTE *pBlob = new BYTE[cbKeyBlob];
PUBLICKEYSTRUC *pPublicKey = (PUBLICKEYSTRUC*)pBlob; pPublicKey->bType = PUBLICKEYBLOB; pPublicKey->bVersion = CUR_BLOB_VERSION; // Always use this value. pPublicKey->reserved = 0; // Must be zero. pPublicKey->aiKeyAlg = CALG_RSA_KEYX; // RSA public-key key exchange.
RSAPUBKEY *pRsaPubKey = (RSAPUBKEY*)(pBlob + sizeof(PUBLICKEYSTRUC)); pRsaPubKey->magic = RSA1; // RSA1 0x31415352 Public key. pRsaPubKey->bitlen = cbModulus * 8; // Number of bits in the modulus. pRsaPubKey->pubexp = dwExponent; // Exponent.
// Copy the modulus into the blob. Put the modulus directly after the // RSAPUBKEY structure in the blob. BYTE *pKey = (BYTE*)(pRsaPubKey + sizeof(RSAPUBKEY)); CopyMemory(pKey, pModulus, cbModulus);
// Now import the key. HCRYPTKEY hCryptKey = NULL; // Receives a handle to the key. CryptImportKey(hCryptProv, pBlob, cbKeyBlob, 0, 0, &hCryptKey);
char* testStr = "test"; BYTE byteArrayText[ 256 ]; memset(byteArrayText, 0, 256); for ( UINT nI = 0; nI < strlen(testStr); ++nI ) byteArrayText[ nI ] = testStr[ nI ];
DWORD dwTextLength = (DWORD)strlen(testStr); DWORD dwBufferLength = 256;
CryptEncrypt( hCryptKey, 0, true, CRYPT_OAEP, byteArrayText, &dwTextLength, dwBufferLength );
wprintf(L"\n\nCryptedText = \""); for (UINT i = 0; i < dwTextLength; i++ ) { wprintf(L"%02x",byteArrayText[i]); } wprintf(L"\n\nCryptedTextReversed = \""); for (int i = dwTextLength-1; i >= 0; i-- ) { wprintf(L"%02x",byteArrayText[i]); }
|
НАШЕЛ ПРИЧИНУ: Неправильно вычислялся указатель на Public Key в структуре PUBLICKEYBLOB :Код | BYTE *pKey = (BYTE*)(pRsaPubKey + sizeof(RSAPUBKEY));
|
pRsaPubKey здесь указатель на RSAPUBKEY , потому если его увеличить на 12(размер в байтах RSAPUBKEY), то указатель увеличится не на 12 байт, как нужно, в нашем случае, а на 12*sizeof(RSAPUBKEY ) и потому адрес начала ключа будет неправильным. Правильный код:Код | BYTE* pKey = pBlob + sizeof(BLOBHEADER)+ sizeof(RSAPUBKEY);
|
Код импорта ключа брал из MSDN, там он с ошибкой: http://msdn.microsoft.com/en-us/library/dd...28VS.85%29.aspxТак что, будьте бдительны, не попадайтесь, как я. ) Это сообщение отредактировал(а) Sokil - 1.10.2010, 14:29
|