Ключи поколения RSA-2048 (публичные и приватные) - PullRequest
1 голос
/ 04 июня 2019

Я делаю простую реализацию RSA-2048. Я нашел код на другом форуме.

#include <string>
#include <iostream>
#include <windows.h>
#include <Wincrypt.h>

using namespace std;

#pragma comment (lib, "Crypt32.lib")

BYTE* Crypt(const string& _str, DWORD* _outLength);

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 main()
{
    string str_data = "test RSA implementation";

    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;
}

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;
}

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 + 1];
    decryptedData[*_length] = 0;
    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;
}

Итак, шифрование \ дешифрование работает на отлично. Мне нужно поменять ключи. Как я могу сгенерировать ключи для этого кода?

Я попробовал этот онлайн генератор, но он не работает. https://travistidwell.com/jsencrypt/demo/ и другие онлайн генераторы

1 Ответ

1 голос
/ 04 июня 2019

NCryptCreatePersistedKey .Пожалуйста, откажитесь от старых функций Crypt * в пользу вариантов NCrypt и BCrypt *.Если вы настаиваете на старом API, используйте this .

...