I'm trying to use the NCrypt.dll to encrypt some data, in C++, and I'm having trouble handling keys and algorithms.
I would like to use AES with the CBC chainging method but, can't get the NCryptEncrypt function to work (I keep getting an invalid buffer size thrown).
I have created and stored a key (in the key storage provider) using the NCRYPT_AES_ALGORITHM flag but, have no idea how to set the algorithm to use the CBC method.
secSt = NCryptCreatePersistedKey(phProvider, &keyHndl, NCRYPT_AES_ALGORITHM, keyname, 0, 0);
I've tried a few property settings and had no success so, I would like to know if this is even possible with NCrypt?
I know the Bcrypt encrypt function allows this and tried to convert my NCRYPT_KEY_HANDLE to a BCRYPT_KEY_HANDLE without success (so I reckon this is not possible).
You can apply the chaining mode CBC by using NCryptSetProperty
and the BCrypt constant BCRYPT_CHAIN_MODE_CBC
.
Note that NCryptEncrypt
does not seem to support padding for symmetric keys (see description of parameter dwFlags
in NCryptEncrypt). So I had to apply some poor man's padding of the clear text to get a multiple of 16 bytes. Without the padding, I also get the status code 0xc0000206 (STATUS_INVALID_BUFFER_SIZE).
// Clear text for testing
static const char* clearText = "The quick brown fox jumps over the lazy dog. 1234567890. ";
static const int clearTextLen = 64;
int main()
{
LPCWSTR keyName = L"NCryptTest";
SECURITY_STATUS status;
NCRYPT_PROV_HANDLE hProvider;
NCRYPT_KEY_HANDLE hKey;
// Open storage provider
status = NCryptOpenStorageProvider(&hProvider, NULL, 0);
// Get stored key
status = NCryptOpenKey(hProvider, &hKey, keyName, 0, 0);
if (status == NTE_BAD_KEYSET)
{
// Create key if it doesn't exist
status = NCryptCreatePersistedKey(hProvider, &hKey, BCRYPT_AES_ALGORITHM, keyName, 0, 0);
status = NCryptFinalizeKey(hKey, 0);
}
// Set the chaining mode CBC
LPCWSTR chainMode = BCRYPT_CHAIN_MODE_CBC;
status = NCryptSetProperty(hKey, NCRYPT_CHAINING_MODE_PROPERTY, (PBYTE)chainMode, wcslen(chainMode) * 2 + 2, 0);
// Encrypt the text
DWORD outlen = -1;
unsigned char* cipherData = new unsigned char[clearTextLen];
status = NCryptEncrypt(hKey, (PBYTE)clearText, clearTextLen, NULL, cipherData, clearTextLen, &outlen, 0);
// Cleanup
delete[] cipherData;
NCryptFreeObject(hKey);
NCryptFreeObject(hProvider);
return 0;
}