locked
Bug in RSA BCryptSignHash? RRS feed

  • Question

  • Hello, this code won't work, no matter what I do. If I use BCryptEncrypt instead of SignHash it works without any problems. I don't know what needs to be changed. Is this a bug in RSA?

    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <bcrypt.h>
    
    #define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
    #define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
    
    #define PrivateKeySize 283
    #define PublicKeySize 155
    #define InputDataSize 118
    
    PUCHAR encryptedBuffer;
    ULONG encryptedBufferSize = 120;
    
    
    VOID printMem(PVOID Mem, int length)
    {
    	int i;
    	for (i = 0; i < length; i++)
    		printf("%02x ", ((unsigned char *)Mem)[i]);
    }
    
    VOID Encrypt()
    {
    	unsigned char PublicKey[PublicKeySize] = { 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,  0x01, 0x00, 0x01, 0xB7,  0x50, 0x52, 0xDD, 0x58, 0xE4, 0x96, 0xAF, 0x91,  0xE5, 0xB2, 0x7B, 0x0A,  0xE6, 0xAA, 0x1F, 0x71,  0x8A, 0x66, 0xC3, 0xF0, 0x21, 0xD8, 0xE6, 0x2C,  0xD6, 0x25, 0x2E, 0x77,  0x3C, 0x61, 0x08, 0x1B,  0x69, 0xE7, 0x58, 0xDF, 0x3B, 0x07, 0xFE, 0xF1,  0xDB, 0xBF, 0xA6, 0x35,  0xDF, 0xC7, 0x49, 0x06,  0xC8, 0xDB, 0x74, 0x2A, 0xB9, 0xED, 0xB3, 0x04,  0x80, 0x75, 0x5F, 0x71,  0x2C, 0xD0, 0x14, 0x0E,  0x81, 0x18, 0x00, 0x5E, 0x34, 0x5A, 0xC2, 0x3A,  0x84, 0x63, 0xB1, 0x6B,  0x04, 0x21, 0x49, 0x7F,  0xE0, 0xF3, 0x52, 0x5E, 0x61, 0x43, 0xB1, 0x8F,  0x7C, 0xF2, 0x74, 0x29,  0x28, 0x69, 0x20, 0x36,  0xC0, 0x92, 0x17, 0x42, 0x99, 0x72, 0xE5, 0xE7,  0x82, 0xBE, 0x8E, 0x3B,  0x3F, 0xC9, 0x0A, 0xE1,  0xC4, 0x63, 0x68, 0x73, 0x1D, 0x67, 0x8D, 0xC0,  0xA3, 0xB4, 0xBA, 0xF0,  0xB7, 0xB0, 0x9B };
    	unsigned char InputData[InputDataSize];
    	BCRYPT_PKCS1_PADDING_INFO padding_PKCS1 = BCRYPT_PKCS1_PADDING_INFO();
    	padding_PKCS1.pszAlgId = BCRYPT_SHA256_ALGORITHM;
    	BCRYPT_ALG_HANDLE hAlgorithm = NULL;
    	BCRYPT_KEY_HANDLE hKey = NULL;
    	NTSTATUS status;
    	printf("size of LPCWSTR : %i\n", sizeof(ULONG));
    	for (int i = 0; i < InputDataSize; i++)
    		InputData[i] = (unsigned char)rand();
    
    	printf("Random Data is \n");
    	printMem(InputData, InputDataSize);
    	printf("\n\n");
    
    	status = BCryptOpenAlgorithmProvider(&hAlgorithm,
    		BCRYPT_RSA_ALGORITHM,
    		NULL,
    		0);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to get algorithm provider..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptImportKeyPair(hAlgorithm,
    		NULL,
    		BCRYPT_RSAPUBLIC_BLOB,
    		&hKey,
    		PublicKey,
    		155,
    		0);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to import Private key..status : %08x\n", status);
    		goto cleanup;
    
    	}
    
    	status = BCryptSignHash(hKey,
    		&padding_PKCS1,
    		InputData,
    		InputDataSize,
    		NULL,
    		0,
    		&encryptedBufferSize,
    		BCRYPT_PAD_PKCS1);
    /*
    	status = BCryptEncrypt(hKey,
    		InputData,
    		InputDataSize,
    		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);
    		goto cleanup;
    	}
    	printf("encryptedBufferSize %i\n", encryptedBufferSize);
    
    	encryptedBuffer = (PUCHAR)HeapAlloc(GetProcessHeap(), 0, encryptedBufferSize);
    
    	if (encryptedBuffer == NULL) {
    		printf("failed to allocate memory for blindedFEKBuffer\n");
    		goto cleanup;
    	}
    
    	status = BCryptSignHash(hKey,
    		&padding_PKCS1,
    		InputData,
    		InputDataSize,
    		encryptedBuffer,
    		encryptedBufferSize,
    		&encryptedBufferSize,
    		BCRYPT_PAD_PKCS1);
    /*
    	status = BCryptEncrypt(hKey,
    		InputData,
    		InputDataSize,
    		NULL,
    		NULL,
    		0,
    		encryptedBuffer,
    		encryptedBufferSize,
    		&encryptedBufferSize,
    		BCRYPT_PAD_PKCS1
    	);
    */
    	if (!NT_SUCCESS(status)) {
    		printf("Failed encrypt data..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	printf("Encrypted Data\n");
    	printMem(encryptedBuffer, encryptedBufferSize);
    	printf("\n\n");
    
    cleanup:
    	if (hKey)
    		BCryptDestroyKey(hKey);
    	if (hAlgorithm)
    		BCryptCloseAlgorithmProvider(hAlgorithm, 0);
    }
    
    
    int __cdecl wmain(
    	int argc,
    	__in_ecount(argc) LPWSTR *wargv)
    {
    
    		Encrypt();
    
    }
    Hope you can help me, thanks in advance.
    • Edited by Matias425326 Monday, March 16, 2020 2:53 AM forgot to ask a question
    Monday, March 16, 2020 2:52 AM

All replies

  • Hello Matias425326,

    BCryptSignHash function creates a signature of a hash value. But BCryptEncrypt function encrypts a block of data. They have different function and output different data: one is a signature and other is ciphertext which is encrypted message.

    A private key is used to sign the hash instead of a public key. Refer to Signing Data with CNG. Your key blob needs contains both private key and public key. And use, for example, BCRYPT_RSAPRIVATE_BLOB instead of BCRYPT_RSAPUBLIC_BLOB.

    Before calling BCryptSignHash, BCryptCreateHash and BCryptHashData are required.

    Finally, BCRYPT_RSA_ALGORITHM is public key algorithm instead of digital signature algorithm, for example, BCRYPT_DSA_ALGORITHM.

    Refer to official sample SignHashAndVerifySignature for how to use BCryptSignHash API.

    Please let me know if it helps.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Tuesday, March 17, 2020 9:58 AM
  • Hi thank you for your answer. I knew that but for some reason I forgot to check, my bad.

    I tried using the PrivateKey now but still same error
    Also on microsoft's docs says:

    BCRYPT_RSA_ALGORITHM
    "RSA"
    The RSA public key algorithm.
    Standard: PKCS #1 v1.5 and v2.0.
    BCRYPT_RSA_SIGN_ALGORITHM
    "RSA_SIGN"
    The RSA signature algorithm. This algorithm is not currently supported. You can use the BCRYPT_RSA_ALGORITHM algorithm to perform RSA signing operations.
    Standard: PKCS #1 v1.5 and v2.0.

    I'm still using BCRYPT_RSA_ALGORITHM but it fails with the same error, This is the updated code:

    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <bcrypt.h>
    
    #define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
    #define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
    
    #define PrivateKeySize 283
    #define PublicKeySize 155
    #define InputDataSize 32
    
    PUCHAR encryptedBuffer;
    ULONG encryptedBufferSize = 32;
    
    
    VOID printMem(PVOID Mem, int length)
    {
    	int i;
    	for (i = 0; i < length; i++)
    		printf("%02x ", ((unsigned char *)Mem)[i]);
    }
    
    VOID Encrypt()
    {
    	unsigned char PrivateKey[PrivateKeySize] = { 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xB7, 0x50, 0x52, 0xDD, 0x58, 0xE4, 0x96, 0xAF, 0x91, 0xE5, 0xB2, 0x7B, 0x0A, 0xE6, 0xAA, 0x1F, 0x71, 0x8A, 0x66, 0xC3, 0xF0, 0x21, 0xD8, 0xE6, 0x2C, 0xD6, 0x25, 0x2E, 0x77, 0x3C, 0x61, 0x08, 0x1B, 0x69, 0xE7, 0x58, 0xDF, 0x3B, 0x07, 0xFE, 0xF1, 0xDB, 0xBF, 0xA6, 0x35, 0xDF, 0xC7, 0x49, 0x06, 0xC8, 0xDB, 0x74, 0x2A, 0xB9, 0xED, 0xB3, 0x04, 0x80, 0x75, 0x5F, 0x71, 0x2C, 0xD0, 0x14, 0x0E, 0x81, 0x18, 0x00, 0x5E, 0x34, 0x5A, 0xC2, 0x3A, 0x84, 0x63, 0xB1, 0x6B, 0x04, 0x21, 0x49, 0x7F, 0xE0, 0xF3, 0x52, 0x5E, 0x61, 0x43, 0xB1, 0x8F, 0x7C, 0xF2, 0x74, 0x29, 0x28, 0x69, 0x20, 0x36, 0xC0, 0x92, 0x17, 0x42, 0x99, 0x72, 0xE5, 0xE7, 0x82, 0xBE, 0x8E, 0x3B, 0x3F, 0xC9, 0x0A, 0xE1, 0xC4, 0x63, 0x68, 0x73, 0x1D, 0x67, 0x8D, 0xC0, 0xA3, 0xB4, 0xBA, 0xF0, 0xB7, 0xB0, 0x9B, 0xBB, 0x3F, 0xB8, 0x6E, 0xC0, 0x34, 0x1E, 0xA0, 0x01, 0x4B, 0x6D, 0x47, 0x73, 0x3F, 0xA5, 0x39, 0x05, 0x27, 0xD4, 0xD1, 0x38, 0x34, 0x32, 0x2C, 0x5B, 0x03, 0x5F, 0x16, 0x21, 0x64, 0x04, 0xD5, 0x19, 0xDB, 0xE7, 0x80, 0xDA, 0xBD, 0xC4, 0x1E, 0xAB, 0x61, 0xC8, 0x84, 0xDF, 0x54, 0x16, 0x77, 0x98, 0x9B, 0x90, 0x03, 0x83, 0xC4, 0x8D, 0x25, 0xB1, 0x32, 0x67, 0x77, 0x6A, 0x1C, 0x64, 0x2D, 0xFA, 0x9E, 0xB9, 0x26, 0xB5, 0xF8, 0x47, 0x4A, 0x9C, 0x35, 0x89, 0x5F, 0x12, 0x0E, 0xFF, 0x60, 0x87, 0x1E, 0x27, 0xC1, 0xC5, 0x7C, 0x77, 0x0A, 0xAE, 0x11, 0x37, 0xE3, 0x42, 0x9B, 0xAF, 0x9D, 0xBC, 0xC2, 0x52, 0xF8, 0x85, 0xBA, 0xED, 0x8E, 0xC3, 0x73, 0x04, 0x0A, 0x53, 0xD2, 0x1D, 0xEF, 0xA0, 0x6A, 0xCD, 0xBE, 0x93, 0x49, 0x34, 0x3A, 0xBD, 0xDF, 0x6A, 0x33, 0x25, 0x91, 0xFC, 0xE7 };
    	unsigned char InputData[InputDataSize];
    	BCRYPT_PKCS1_PADDING_INFO padding_PKCS1 = BCRYPT_PKCS1_PADDING_INFO();
    	padding_PKCS1.pszAlgId = BCRYPT_SHA256_ALGORITHM;
    	BCRYPT_ALG_HANDLE hAlgorithm = NULL;
    	BCRYPT_KEY_HANDLE hKey = NULL;
    	NTSTATUS status;
    	for (int i = 0; i < InputDataSize; i++)
    		InputData[i] = (unsigned char)rand();
    
    	printf("Random Data is \n");
    	printMem(InputData, InputDataSize);
    	printf("\n\n");
    
    	status = BCryptOpenAlgorithmProvider(&hAlgorithm,
    		BCRYPT_RSA_ALGORITHM,
    		NULL,
    		0);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to get algorithm provider..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptImportKeyPair(hAlgorithm,
    		NULL,
    		BCRYPT_RSAPRIVATE_BLOB,
    		&hKey,
    		PrivateKey,
    		PrivateKeySize,
    		BCRYPT_NO_KEY_VALIDATION);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to import Private key..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptSignHash(hKey,
    		NULL,
    		InputData,
    		InputDataSize,
    		NULL,
    		0,
    		&encryptedBufferSize,
    		0);
    /*
    	status = BCryptEncrypt(hKey,
    		InputData,
    		InputDataSize,
    		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);
    		goto cleanup;
    	}
    	printf("encryptedBufferSize %i\n", encryptedBufferSize);
    
    	encryptedBuffer = (PUCHAR)HeapAlloc(GetProcessHeap(), 0, encryptedBufferSize);
    
    	if (encryptedBuffer == NULL) {
    		printf("failed to allocate memory for blindedFEKBuffer\n");
    		goto cleanup;
    	}
    
    	status = BCryptSignHash(hKey,
    		NULL,
    		InputData,
    		InputDataSize,
    		encryptedBuffer,
    		encryptedBufferSize,
    		&encryptedBufferSize,
    		0);
    /*
    	status = BCryptEncrypt(hKey,
    		InputData,
    		InputDataSize,
    		NULL,
    		NULL,
    		0,
    		encryptedBuffer,
    		encryptedBufferSize,
    		&encryptedBufferSize,
    		BCRYPT_PAD_PKCS1
    	);
    */
    	if (!NT_SUCCESS(status)) {
    		printf("Failed sign data..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	printf("Encrypted Data\n");
    	printMem(encryptedBuffer, encryptedBufferSize);
    	printf("\n\n");
    
    cleanup:
    	if (hKey)
    		BCryptDestroyKey(hKey);
    	if (hAlgorithm)
    		BCryptCloseAlgorithmProvider(hAlgorithm, 0);
    }
    
    
    int __cdecl wmain(
    	int argc,
    	__in_ecount(argc) LPWSTR *wargv)
    {
    
    		Encrypt();
    
    }

    I even added the hash operation so the input data is actually a hash but still same error:
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <bcrypt.h>
    
    #define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
    #define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)
    
    #define PrivateKeySize 283
    #define PublicKeySize 155
    #define InputDataSize 32
    
    PUCHAR encryptedBuffer;
    ULONG encryptedBufferSize = 32;
    
    
    VOID printMem(PVOID Mem, int length)
    {
    	int i;
    	for (i = 0; i < length; i++)
    		printf("%02x ", ((unsigned char *)Mem)[i]);
    }
    
    VOID Encrypt()
    {
    	unsigned char PrivateKey[PrivateKeySize] = { 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xB7, 0x50, 0x52, 0xDD, 0x58, 0xE4, 0x96, 0xAF, 0x91, 0xE5, 0xB2, 0x7B, 0x0A, 0xE6, 0xAA, 0x1F, 0x71, 0x8A, 0x66, 0xC3, 0xF0, 0x21, 0xD8, 0xE6, 0x2C, 0xD6, 0x25, 0x2E, 0x77, 0x3C, 0x61, 0x08, 0x1B, 0x69, 0xE7, 0x58, 0xDF, 0x3B, 0x07, 0xFE, 0xF1, 0xDB, 0xBF, 0xA6, 0x35, 0xDF, 0xC7, 0x49, 0x06, 0xC8, 0xDB, 0x74, 0x2A, 0xB9, 0xED, 0xB3, 0x04, 0x80, 0x75, 0x5F, 0x71, 0x2C, 0xD0, 0x14, 0x0E, 0x81, 0x18, 0x00, 0x5E, 0x34, 0x5A, 0xC2, 0x3A, 0x84, 0x63, 0xB1, 0x6B, 0x04, 0x21, 0x49, 0x7F, 0xE0, 0xF3, 0x52, 0x5E, 0x61, 0x43, 0xB1, 0x8F, 0x7C, 0xF2, 0x74, 0x29, 0x28, 0x69, 0x20, 0x36, 0xC0, 0x92, 0x17, 0x42, 0x99, 0x72, 0xE5, 0xE7, 0x82, 0xBE, 0x8E, 0x3B, 0x3F, 0xC9, 0x0A, 0xE1, 0xC4, 0x63, 0x68, 0x73, 0x1D, 0x67, 0x8D, 0xC0, 0xA3, 0xB4, 0xBA, 0xF0, 0xB7, 0xB0, 0x9B, 0xBB, 0x3F, 0xB8, 0x6E, 0xC0, 0x34, 0x1E, 0xA0, 0x01, 0x4B, 0x6D, 0x47, 0x73, 0x3F, 0xA5, 0x39, 0x05, 0x27, 0xD4, 0xD1, 0x38, 0x34, 0x32, 0x2C, 0x5B, 0x03, 0x5F, 0x16, 0x21, 0x64, 0x04, 0xD5, 0x19, 0xDB, 0xE7, 0x80, 0xDA, 0xBD, 0xC4, 0x1E, 0xAB, 0x61, 0xC8, 0x84, 0xDF, 0x54, 0x16, 0x77, 0x98, 0x9B, 0x90, 0x03, 0x83, 0xC4, 0x8D, 0x25, 0xB1, 0x32, 0x67, 0x77, 0x6A, 0x1C, 0x64, 0x2D, 0xFA, 0x9E, 0xB9, 0x26, 0xB5, 0xF8, 0x47, 0x4A, 0x9C, 0x35, 0x89, 0x5F, 0x12, 0x0E, 0xFF, 0x60, 0x87, 0x1E, 0x27, 0xC1, 0xC5, 0x7C, 0x77, 0x0A, 0xAE, 0x11, 0x37, 0xE3, 0x42, 0x9B, 0xAF, 0x9D, 0xBC, 0xC2, 0x52, 0xF8, 0x85, 0xBA, 0xED, 0x8E, 0xC3, 0x73, 0x04, 0x0A, 0x53, 0xD2, 0x1D, 0xEF, 0xA0, 0x6A, 0xCD, 0xBE, 0x93, 0x49, 0x34, 0x3A, 0xBD, 0xDF, 0x6A, 0x33, 0x25, 0x91, 0xFC, 0xE7 };
    	unsigned char InputData[InputDataSize];
    	BCRYPT_PKCS1_PADDING_INFO padding_PKCS1 = BCRYPT_PKCS1_PADDING_INFO();
    	padding_PKCS1.pszAlgId = BCRYPT_SHA256_ALGORITHM;
    	BCRYPT_ALG_HANDLE hAlgorithm = NULL;
    	BCRYPT_ALG_HANDLE hHashAlg = NULL;
    	DWORD cbHashObject = 0;
    	DWORD cbData = 0;
    	DWORD cbHash = 0;
    	PBYTE pbHashObject = NULL;
    	PBYTE pbHash = NULL;
    	BCRYPT_HASH_HANDLE hHash = NULL;
    	BCRYPT_KEY_HANDLE hKey = NULL;
    	NTSTATUS status;
    	for (int i = 0; i < InputDataSize; i++)
    		InputData[i] = (unsigned char)rand();
    
    	printf("Random Data is \n");
    	printMem(InputData, InputDataSize);
    	printf("\n\n");
    
    	//open an algorithm handle
    	status = BCryptOpenAlgorithmProvider(
    		&hHashAlg,
    		BCRYPT_SHA1_ALGORITHM,
    		NULL,
    		0);
    	
    	if (!NT_SUCCESS(status)) {
    		wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
    		goto cleanup;
    	}
    
    	//calculate the size of the buffer to hold the hash object
    	status = BCryptGetProperty(
    		hHashAlg,
    		BCRYPT_OBJECT_LENGTH,
    		(PBYTE)&cbHashObject,
    		sizeof(DWORD),
    		&cbData,
    		0);
    
    	if (!NT_SUCCESS(status)) {
    		wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
    		goto cleanup;
    	}
    
    
    	//allocate the hash object on the heap
    	pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
    	if (NULL == pbHashObject)
    	{
    		wprintf(L"**** memory allocation failed\n");
    		goto cleanup;
    	}
    
    	//calculate the length of the hash
    	status = BCryptGetProperty(
    		hHashAlg,
    		BCRYPT_HASH_LENGTH,
    		(PBYTE)&cbHash,
    		sizeof(DWORD),
    		&cbData,
    		0);
    	
    	if (!NT_SUCCESS(status))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
    		goto cleanup;
    	}
    
    	//allocate the hash buffer on the heap
    	pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
    	if (NULL == pbHash)
    	{
    		wprintf(L"**** memory allocation failed\n");
    		goto cleanup;
    	}
    
    	//create a hash
    	status = BCryptCreateHash(
    		hHashAlg,
    		&hHash,
    		pbHashObject,
    		cbHashObject,
    		NULL,
    		0,
    		0);
    
    	if (!NT_SUCCESS(status))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
    		goto cleanup;
    	}
    
    
    	//hash some data
    	status = BCryptHashData(
    		hHash,
    		(PBYTE)InputData,
    		sizeof(InputData),
    		0);
    
    	if (!NT_SUCCESS(status))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
    		goto cleanup;
    	}
    
    	//close the hash
    	if (!NT_SUCCESS(status = BCryptFinishHash(
    		hHash,
    		pbHash,
    		cbHash,
    		0)))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptOpenAlgorithmProvider(&hAlgorithm,
    		BCRYPT_RSA_ALGORITHM,
    		NULL,
    		0);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to get algorithm provider..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptImportKeyPair(hAlgorithm,
    		NULL,
    		BCRYPT_RSAPRIVATE_BLOB,
    		&hKey,
    		PrivateKey,
    		PrivateKeySize,
    		BCRYPT_NO_KEY_VALIDATION);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to import Private key..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptSignHash(hKey,
    		NULL,
    		pbHash,
    		cbHash,
    		NULL,
    		0,
    		&encryptedBufferSize,
    		0);
    /*
    	status = BCryptEncrypt(hKey,
    		InputData,
    		InputDataSize,
    		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);
    		goto cleanup;
    	}
    	printf("encryptedBufferSize %i\n", encryptedBufferSize);
    
    	encryptedBuffer = (PUCHAR)HeapAlloc(GetProcessHeap(), 0, encryptedBufferSize);
    
    	if (encryptedBuffer == NULL) {
    		printf("failed to allocate memory for blindedFEKBuffer\n");
    		goto cleanup;
    	}
    
    	status = BCryptSignHash(hKey,
    		NULL,
    		pbHash,
    		cbHash,
    		encryptedBuffer,
    		encryptedBufferSize,
    		&encryptedBufferSize,
    		0);
    /*
    	status = BCryptEncrypt(hKey,
    		InputData,
    		InputDataSize,
    		NULL,
    		NULL,
    		0,
    		encryptedBuffer,
    		encryptedBufferSize,
    		&encryptedBufferSize,
    		BCRYPT_PAD_PKCS1
    	);
    */
    	if (!NT_SUCCESS(status)) {
    		printf("Failed sign data..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	printf("Encrypted Data\n");
    	printMem(encryptedBuffer, encryptedBufferSize);
    	printf("\n\n");
    
    cleanup:
    	if (hKey)
    		BCryptDestroyKey(hKey);
    	if (hAlgorithm)
    		BCryptCloseAlgorithmProvider(hAlgorithm, 0);
    }
    
    
    int __cdecl wmain(
    	int argc,
    	__in_ecount(argc) LPWSTR *wargv)
    {
    
    		Encrypt();
    
    }

    • Edited by Matias425326 Tuesday, March 17, 2020 11:17 AM Added a new code
    Tuesday, March 17, 2020 11:06 AM
  • Hello Matias425326,

    Padding is required for RSA algorithm.

    And also note you use SHA1 algorithm for hashing, so padding algorithm must be SHA1. If you want to use SHA256 for padding, you need use SHA256 for hashing too.

    The following is complete code works for me. You can have a try.

    VOID Encrypt()
    {
    	unsigned char PrivateKey[PrivateKeySize] = { 0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xB7, 0x50, 0x52, 0xDD, 0x58, 0xE4, 0x96, 0xAF, 0x91, 0xE5, 0xB2, 0x7B, 0x0A, 0xE6, 0xAA, 0x1F, 0x71, 0x8A, 0x66, 0xC3, 0xF0, 0x21, 0xD8, 0xE6, 0x2C, 0xD6, 0x25, 0x2E, 0x77, 0x3C, 0x61, 0x08, 0x1B, 0x69, 0xE7, 0x58, 0xDF, 0x3B, 0x07, 0xFE, 0xF1, 0xDB, 0xBF, 0xA6, 0x35, 0xDF, 0xC7, 0x49, 0x06, 0xC8, 0xDB, 0x74, 0x2A, 0xB9, 0xED, 0xB3, 0x04, 0x80, 0x75, 0x5F, 0x71, 0x2C, 0xD0, 0x14, 0x0E, 0x81, 0x18, 0x00, 0x5E, 0x34, 0x5A, 0xC2, 0x3A, 0x84, 0x63, 0xB1, 0x6B, 0x04, 0x21, 0x49, 0x7F, 0xE0, 0xF3, 0x52, 0x5E, 0x61, 0x43, 0xB1, 0x8F, 0x7C, 0xF2, 0x74, 0x29, 0x28, 0x69, 0x20, 0x36, 0xC0, 0x92, 0x17, 0x42, 0x99, 0x72, 0xE5, 0xE7, 0x82, 0xBE, 0x8E, 0x3B, 0x3F, 0xC9, 0x0A, 0xE1, 0xC4, 0x63, 0x68, 0x73, 0x1D, 0x67, 0x8D, 0xC0, 0xA3, 0xB4, 0xBA, 0xF0, 0xB7, 0xB0, 0x9B, 0xBB, 0x3F, 0xB8, 0x6E, 0xC0, 0x34, 0x1E, 0xA0, 0x01, 0x4B, 0x6D, 0x47, 0x73, 0x3F, 0xA5, 0x39, 0x05, 0x27, 0xD4, 0xD1, 0x38, 0x34, 0x32, 0x2C, 0x5B, 0x03, 0x5F, 0x16, 0x21, 0x64, 0x04, 0xD5, 0x19, 0xDB, 0xE7, 0x80, 0xDA, 0xBD, 0xC4, 0x1E, 0xAB, 0x61, 0xC8, 0x84, 0xDF, 0x54, 0x16, 0x77, 0x98, 0x9B, 0x90, 0x03, 0x83, 0xC4, 0x8D, 0x25, 0xB1, 0x32, 0x67, 0x77, 0x6A, 0x1C, 0x64, 0x2D, 0xFA, 0x9E, 0xB9, 0x26, 0xB5, 0xF8, 0x47, 0x4A, 0x9C, 0x35, 0x89, 0x5F, 0x12, 0x0E, 0xFF, 0x60, 0x87, 0x1E, 0x27, 0xC1, 0xC5, 0x7C, 0x77, 0x0A, 0xAE, 0x11, 0x37, 0xE3, 0x42, 0x9B, 0xAF, 0x9D, 0xBC, 0xC2, 0x52, 0xF8, 0x85, 0xBA, 0xED, 0x8E, 0xC3, 0x73, 0x04, 0x0A, 0x53, 0xD2, 0x1D, 0xEF, 0xA0, 0x6A, 0xCD, 0xBE, 0x93, 0x49, 0x34, 0x3A, 0xBD, 0xDF, 0x6A, 0x33, 0x25, 0x91, 0xFC, 0xE7 };
    	unsigned char InputData[InputDataSize];
    	BCRYPT_PKCS1_PADDING_INFO padding_PKCS1 = BCRYPT_PKCS1_PADDING_INFO();
    	padding_PKCS1.pszAlgId = BCRYPT_SHA256_ALGORITHM;
    	BCRYPT_ALG_HANDLE hAlgorithm = NULL;
    	BCRYPT_ALG_HANDLE hHashAlg = NULL;
    	DWORD cbHashObject = 0;
    	DWORD cbData = 0;
    	DWORD cbHash = 0;
    	PBYTE pbHashObject = NULL;
    	PBYTE pbHash = NULL;
    	BCRYPT_HASH_HANDLE hHash = NULL;
    	BCRYPT_KEY_HANDLE hKey = NULL;
    	NTSTATUS status;
    
    	for (int i = 0; i < InputDataSize; i++)
    		InputData[i] = (unsigned char)rand();
    
    	printf("Random Data is \n");
    	printMem(InputData, InputDataSize);
    	printf("\n\n");
    
    	//open an algorithm handle
    	status = BCryptOpenAlgorithmProvider(
    		&hHashAlg,
    		BCRYPT_SHA256_ALGORITHM,
    		NULL,
    		0);
    
    	if (!NT_SUCCESS(status)) {
    		wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
    		goto cleanup;
    	}
    
    	//calculate the size of the buffer to hold the hash object
    	status = BCryptGetProperty(
    		hHashAlg,
    		BCRYPT_OBJECT_LENGTH,
    		(PBYTE)&cbHashObject,
    		sizeof(DWORD),
    		&cbData,
    		0);
    
    	if (!NT_SUCCESS(status)) {
    		wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
    		goto cleanup;
    	}
    
    
    	//allocate the hash object on the heap
    	pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
    	if (NULL == pbHashObject)
    	{
    		wprintf(L"**** memory allocation failed\n");
    		goto cleanup;
    	}
    
    	//calculate the length of the hash
    	status = BCryptGetProperty(
    		hHashAlg,
    		BCRYPT_HASH_LENGTH,
    		(PBYTE)&cbHash,
    		sizeof(DWORD),
    		&cbData,
    		0);
    
    	if (!NT_SUCCESS(status))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
    		goto cleanup;
    	}
    
    	//allocate the hash buffer on the heap
    	pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
    	if (NULL == pbHash)
    	{
    		wprintf(L"**** memory allocation failed\n");
    		goto cleanup;
    	}
    
    	//create a hash
    	status = BCryptCreateHash(
    		hHashAlg,
    		&hHash,
    		pbHashObject,
    		cbHashObject,
    		NULL,
    		0,
    		0);
    
    	if (!NT_SUCCESS(status))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
    		goto cleanup;
    	}
    
    	//hash some data
    	status = BCryptHashData(
    		hHash,
    		(PBYTE)InputData,
    		sizeof(InputData),
    		0);
    
    	if (!NT_SUCCESS(status))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
    		goto cleanup;
    	}
    
    	//close the hash
    	if (!NT_SUCCESS(status = BCryptFinishHash(
    		hHash,
    		pbHash,
    		cbHash,
    		0)))
    	{
    		wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptOpenAlgorithmProvider(&hAlgorithm,
    		BCRYPT_RSA_ALGORITHM,
    		NULL,
    		0);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to get algorithm provider..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptImportKeyPair(hAlgorithm,
    		NULL,
    		BCRYPT_RSAPRIVATE_BLOB,
    		&hKey,
    		PrivateKey,
    		PrivateKeySize,
    		BCRYPT_NO_KEY_VALIDATION);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to import Private key..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	status = BCryptSignHash(hKey,
    		&padding_PKCS1,
    		pbHash,
    		cbHash,
    		NULL,
    		0,
    		&encryptedBufferSize,
    		BCRYPT_PAD_PKCS1);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed to get required size of buffer..status : %08x\n", status);
    		goto cleanup;
    	}
    	printf("encryptedBufferSize %i\n", encryptedBufferSize);
    
    	encryptedBuffer = (PUCHAR)HeapAlloc(GetProcessHeap(), 0, encryptedBufferSize);
    
    	if (encryptedBuffer == NULL) {
    		printf("failed to allocate memory for blindedFEKBuffer\n");
    		goto cleanup;
    	}
    
    	status = BCryptSignHash(hKey,
    		&padding_PKCS1,
    		pbHash,
    		cbHash,
    		encryptedBuffer,
    		encryptedBufferSize,
    		&encryptedBufferSize,
    		BCRYPT_PAD_PKCS1);
    	if (!NT_SUCCESS(status)) {
    		printf("Failed sign data..status : %08x\n", status);
    		goto cleanup;
    	}
    
    	printf("Encrypted Data\n");
    	printMem(encryptedBuffer, encryptedBufferSize);
    	printf("\n\n");
    
    cleanup:
    	if (hKey)
    		BCryptDestroyKey(hKey);
    	if (hAlgorithm)
    		BCryptCloseAlgorithmProvider(hAlgorithm, 0);
    }
    

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, March 18, 2020 7:08 AM
  • Hello, it works now!. But found another problem.

    When calculating the signature of the same data, same padding, keyPair and hash on php, it outputs a different signature for some reason. I'm using:

    openssl_sign
    Do you know what does this happen?
    Thursday, March 19, 2020 12:20 PM
  • Hello Matias425326,

    This forum is for "Discuss writing secure applications for the Windows platform." It is Win32 C++ focused.

    I'm not an expert in PHP, maybe you can ask a question at Stackoverflow.com for help.

    Hope it helps.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, March 20, 2020 5:49 AM
  • Hello Matias425326,

    This forum is for "Discuss writing secure applications for the Windows platform." It is Win32 C++ focused.

    I'm not an expert in PHP, maybe you can ask a question at Stackoverflow.com for help.

    Hope it helps.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Hello, I appreciate your help. The problem is that this is something about CNG, every other application even on java or python the signature is the same as the one in php. But when using CNG I get a different signature, I don't know what's wrong to fix it.
    Saturday, March 21, 2020 5:11 PM
  • Hello Matias425326,

    Could you verify the signature created using CNG APIs to see if it can be verified successfully?

    Refer to BCryptVerifySignature and an example of how to verify.

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, March 23, 2020 6:33 AM