2023-09-27

Asymmetric Encryption of data with BCrypt.lib at c++ side and decrypting with RSACryptoServiceProvider at c# side. (Parameter is Incorrect)

I am having a windows service written in .NET (C#) and a library written in CPP. I am generating the Public/Private Key pair in .NET side with RSACryptoServiceProvider and send the Public Key information to CPP side. At c++ end, After importing the Public Key received from C#, I am Encrypting my data with BCrypt.lib library and returning it to .net service by encoding it into base64. Now at .Net side, I am decrypting the encoded data received from c++ using RSACryptoServiceProvider.

During RSA.Decrypt() method call I am getting below exception: CryptographicException: 'The parameter is incorrect'

It seems some encoding issue to me but I am no expert here.

I have tried below solutions:

  • Using Convert.FromBase64String() method to convert the received base64 data into byte array.
  • I have tried to reverse the byte array received from above conversion.

Below are the code snippet I am working on.

.Net Side Code:

var rsa = RSACryptoServiceProvider.Create(1024);
var publicKey = rsa.ToXmlString(false);

var encryptedData = Convert.FromBase64String(GetEncryptedDataFromCPP(publicKey));
//Array.Reverse(encryptedData); 

byte[] decryptedData = rsa.Decrypt(encryptedData, RSAEncryptionPadding.Pkcs1); //CryptographyException: Invalid Parameter
var decryptedDataValue = Encoding.UTF8.GetString(decryptedData);

.C++ Side Code:

VOID GetEncryptedDataFromCPP(publicKey)
{
    BYTE* pbPublicKey = NULL;
    DWORD cbExp = 3;
    DWORD cbModulus = 128;
    DWORD cbKey = cbExp + sizeof(BCRYPT_RSAKEY_BLOB) + cbModulus;
    BCRYPT_RSAKEY_BLOB* pRsaBlob;
    PBYTE pbCurrent;

//**Assuming I have fetched the Modulus and Exponent from the xml string and assigned as below.**
    std::string modulus = "3XCSEveWJ3Mp41g5VxcmmlCYDL5X+VUX1ULOIl8TdsEu6bbS/Ho0ofBgAwglCrbRgAjm7ZW+EivEVLZRx5FVsEYqGX12fFZSn84Ye6D2rUYqvwR0kBE8MBCdirqg3gXAlmuIgxucWcxiT9NDTaC67Awe9yyQv3fJ2uPeOEXw0LU=";
    std::string exponent = "AQAB";

    std::vector<BYTE> PubKeyModulus_bin = base64_decode(PubKeyModulus);
    std::vector<BYTE> PubKeyExp_bin = base64_decode(PubKeyExp);
    
    pbPublicKey = (BYTE*)CoTaskMemAlloc(cbKey);
    ZeroMemory(pbPublicKey, cbKey);
    pRsaBlob = (BCRYPT_RSAKEY_BLOB*)(pbPublicKey);
    // Make the Public Key Blob Header
    pRsaBlob->Magic = BCRYPT_RSAPUBLIC_MAGIC;
    pRsaBlob->BitLength = 128*8;
    pRsaBlob->cbPublicExp = 3;
    pRsaBlob->cbModulus = 128;
    pRsaBlob->cbPrime1 = 0;
    pRsaBlob->cbPrime2 = 0;
    
    BCRYPT_ALG_HANDLE hAlgorithm = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;
    NTSTATUS status;

    BYTE textData[] = "test";
    DWORD textDataSize = sizeof(textData);
    
    status = BCryptOpenAlgorithmProvider(&hAlgorithm,
        BCRYPT_RSA_ALGORITHM,
        NULL,
        0);
    if (!NT_SUCCESS(status)) {
        printf("Failed to get algorithm provider..status : %08x\n", status);
    }

    status = BCryptImportKeyPair(hAlgorithm,
        NULL,
        BCRYPT_RSAPUBLIC_BLOB,
        &hKey,
        (PUCHAR)pbPublicKey,
        cbKey,//155,
        BCRYPT_NO_KEY_VALIDATION);
    if (!NT_SUCCESS(status)) {
        printf("Failed to import Private key..status : %08x\n", status);
    }  
        
    status = BCryptEncrypt(hKey,
        textData,
        textDataSize,
        NULL,
        NULL,
        0,
        NULL,
        0,
        &encryptedBufferSize,
        BCRYPT_PAD_PKCS1
    );
    if (!NT_SUCCESS(status)) {
        printf("Failed to get required size of buffer..status : %08x\n", status);
    }

    encryptedBuffer = (PUCHAR)HeapAlloc(GetProcessHeap(), 0, encryptedBufferSize);

    if (encryptedBuffer == NULL) {
        printf("failed to allocate memory for blindedFEKBuffer\n");
    }

    status = BCryptEncrypt(hKey,
        textData,
        textDataSize,
        NULL,
        NULL,
        0,
        encryptedBuffer,
        encryptedBufferSize,
        &encryptedBufferSize,
        BCRYPT_PAD_PKCS1
    );

    if (!NT_SUCCESS(status)) {
        printf("Failed encrypt data..status : %08x\n", status);
    }
    printf("Encrypted Data\n");
    printMem(encryptedBuffer, encryptedBufferSize);
    printf("\n\n");

    std::string encryptedDataReturn = base64_encode(&encData[0], encDataSize);

    }
}

ReverseMemCpy (In Case of Little Endian, I am hoping this is the correct way)

void ReverseMemCopy(BYTE* pbDest, BYTE const* pbSource, DWORD cb)
{
    for (DWORD i = 0; i < cb; i++)
    {
        //pbDest[cb - 1 - i] = pbSource[i];   // in case of Big Endian
        pbDest[i] = pbSource[i];
    }
}

Required Input and Output from Code:

Input Data: test

My Public/Private Key Pair: (Generated at .Net Side)

<RSAKeyValue><Modulus>3XCSEveWJ3Mp41g5VxcmmlCYDL5X+VUX1ULOIl8TdsEu6bbS/Ho0ofBgAwglCrbRgAjm7ZW+EivEVLZRx5FVsEYqGX12fFZSn84Ye6D2rUYqvwR0kBE8MBCdirqg3gXAlmuIgxucWcxiT9NDTaC67Awe9yyQv3fJ2uPeOEXw0LU=</Modulus><Exponent>AQAB</Exponent><P>8uB+2rMMnduKEZ/j9pIkNuHPjqOaeBi0DMkfVTHlrknVdDwCreKVHEx9XIEyYQeYdpCwmj8hwHMEVmHJhVUcjw==</P><Q>6WeNjG2cOZ6y6e+A0k12Bn5UX/HNgeBjdfyy67PG9FMioJ9znAZsJmM5dWaQD9Px3OaHEp5tJhlqrUc6U25oew==</Q><DP>FMpW0Y3GJLUoSn3vW6oC45fM1p72mBU1RGrq/bX5vUOgvARvDkd5ECUUDhkZIOkviea0119UGk8+Lc7NG1a/zQ==</DP><DQ>Sda9vAhNHRlspn9jdKSWyxUaIkQ/7G+NZ50rCVAVh+PpF4F6NIj/m+FWIyLwPmGhqW2wm55ND3mI+wqGlDBgkw==</DQ><InverseQ>Pz8NIq8+1o6PXWdWJUJPyV1Wli9NdK5RlH8yc44QJYzAxcEFnI8CPHkQu0BHrN+mfOX9UN7LfHjI9wmOVStksw==</InverseQ><D>NjayPJyLEXt7fOKDn1PWqp8iqrQLO8ree+LQLtASJtfjEWsmOpP8wMzl5LggwX/CyNLlHrOzhiVa+tZsLSziykG4CzY1qwL6HS+oSoR7GbjkSZXQPbN8RM2tS8fZ0ZyRAtn7ohDRFNMZe6Y+cFQ3H2ijARpVl4VngTqyK/Syyz0=</D></RSAKeyValue>"

Encrypted Data in Base64:

kycXjy03kP+VjWP4uYFMl4/avSOhJ269BZM/AeEj0RQmSgkfA+m9woENkDVqQuxOuw8/DqpeNreA7p11QOu3i5WNJ2wC2zhCVgXi0z+tjylQidAKiwNFNlvEfAQN3h18F/gLKkuCH7W3a7tqigxZc2jCOflA4ZeGx54ZL+gVDAw=

Encrypted Data in hex/BYTE form:

93 27 17 8f 2d 37 90 ff 95 8d 63 f8 b9 81 4c 97 8f da bd 23 a1 27 6e bd 05 93 3f 01 e1 23 d1 14 26 4a 09 1f 03 e9 bd c2 81 0d 90 35 6a 42 ec 4e bb 0f 3f 0e aa 5e 36 b7 80 ee 9d 75 40 eb b7 8b 95 8d 27 6c 02 db 38 42 56 05 e2 d3 3f ad 8f 29 50 89 d0 0a 8b 03 45 36 5b c4 7c 04 0d de 1d 7c 17 f8 0b 2a 4b 82 1f b5 b7 6b bb 6a 8a 0c 59 73 68 c2 39 f9 40 e1 97 86 c7 9e 19 2f e8 15 0c 0c

Exception at .Net Side in Decrypt()

System.Security.Cryptography.CryptographicException: 'The parameter is incorrect



No comments:

Post a Comment