На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Шифрование RSA. Crypto API и .pem ключи сгенерированные через openssl.
    Привет.
    Сейчас я пытаюсь написать программу, которая будет шифровать и дешифровать текстовые данные используя алгоритм RSA и вшитые в код закрытый и открытый ключи.
    Ключи я генерирую через openssl.

    Вот попытался набросать программу которая будет шифровать текст. Сперва я преобразовываю закрытый ключ в форму с которой может работать Crypto API а затем пытаюсь выполнить шифрование.
    ExpandedWrap disabled
      #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), по идее, должно быть достаточно.
    Помогите разобраться.
      Немоного подправил программу
      ExpandedWrap disabled
        #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. Я новичок в этом деле. Серьезно, нужно помощь )
      Сообщение отредактировано: CantStop0708 -
        ExpandedWrap disabled
             // 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
        Сообщение отредактировано: leo -
          Понял.
          Теперь попытался сделать дешифрование и снова не смог понять что не так.
          Шифрование и дешифрование теперь вынесены в функции Crypt() и Decrypt().
          При дешифровании CryptDecrypt() вылетает с ошибкой NTE_NO_KEY, хотя параметр hKey под отладчиком вовсе не пустой.
          ExpandedWrap disabled
            #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;
            }
            Цитата CantStop0708 @
            При дешифровании CryptDecrypt() вылетает с ошибкой NTE_NO_KEY, хотя параметр hKey под отладчиком вовсе не пустой.

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

            Цитата CantStop0708 @
            string Crypt(const string& _str)
            {...
            std::string s(reinterpret_cast<char const*>(cipherBlock));
            return s;
            }
            Ты не думаешь, что при таком копировании бинарных данных в строку происходит обрезка их длины по первому нулевому байту? Нужно либо возвращать данные as is как массив BYTE*, либо кодировать их в строку BASE64 или HEX. К тому же после преобразования\копирования в строку исходный cipherBlock нужно удалить
            Сообщение отредактировано: leo -
              Исправил. Теперь шифруем публичным ключом и дешифруем приватным. Возвращаем данные as is как массив BYTE*.
              При дешифровании считываем длинну дешифрованной строки, которая в общем-то правильно определяется, но при выводе почему-то в конец строки дописывается 4 лишних символа.
              То есть, если изначально строка была 1234567890ABCDEFGH, то при выводе имеем 1234567890ABCDEFGH****
              ExpandedWrap disabled
                #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;
                }
                Цитата CantStop0708 @
                При дешифровании считываем длинну дешифрованной строки, которая в общем-то правильно определяется, но при выводе почему-то в конец строки дописывается 4 лишних символа.

                Попробуй так:
                ExpandedWrap disabled
                  //...
                  //...
                          // Decrypted data
                          BYTE* decryptedData = new BYTE[*_length+1];
                          decryptedData[*_length]=0;
                          memcpy((void *)decryptedData, cipherBlock, *_length);
                  //...
                  //...


                Или:
                ExpandedWrap disabled
                  //...
                          BYTE* decryptedData = Decrypt(encrytedData, &encryptedDataLen);
                   
                          for(DWORD i=0;i<encryptedDataLen;++i)  { cout << decryptedData[i];}  cout << endl;
                       //   cout << decryptedData << endl;
                  //...
                Сообщение отредактировано: ЫукпШ -
                  CantStop0708
                  В CryptAcquireContext в качестве провайдера нужно указывать MS_ENHANCED_PROV
                    Цитата ЫукпШ @
                    Попробуй так:
                    ExpandedWrap disabled
                          //...
                          //...
                                  // 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 вообще не вариант? И можно ли тогда вообще использовать готовые библиотеки, раз такое дело, или только вручную кодировать алгоритм чтобы быть уверенным что он работает одинаково?
                      Цитата 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), разные флаги и т.п., то не исключено ;)
                        Всем благодарности за помощь.
                          Целый вирус шифровальщик получается :jokingly:
                            Привет всем.
                            Вопрос не совсем по теме, но близок, поэтому спрошу здесь.
                            ---
                            Пытаюсь использовать CryptoAPI (Windows), RSA асимметричным алгоритмом.
                            Вроде-бы всё получается - ключи создаются, сообщение шифруется/дешифруется, всё хорошо.
                            Однако обнаружен странный эффект - если произвести де-шифрование на той-же машине,
                            где создавались ключи - тогда для де-шифрования можно использовать публичный ключ. :blink:
                            ---
                            Если передать публичный ключ на другую машину физически, тогда всё получается как надо.
                            Зашифровать можно, расшифровать - нет.
                            На машине, где генерировались ключи, для де-шифрования подходит любой из них.
                            Значит, приватный ключ вообще не нужен ? :huh:
                            ---
                            Это какая-то ошибка или я что-то не правильно делаю ?
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script execution time: 0,0510 ]   [ 16 queries used ]   [ Generated: 29.03.24, 08:44 GMT ]