An OPAQUEKEYBLOB exported via CryptExportKey on Windows 7 is incompatible with Windows 8.1
Artigo
I recently ran into a customer having decryption problems on Windows 8.1.
The data was encrypted using a symmetric key created on Windows 7 and exported as an OPAQUEKEYBLOB.
When importing the key on Windows 8.1 and then attempting to decrypt, CryptDecrypt failed with NTE_BAD_DATA.
It turns out that there was a fair amount of code change to CryptoAPI on Windows 8.1 and the OPAQUEKEYBLOB is slightly different from Windows 7.
The key blob is compatible moving in the following directions:
Win 7 -> Win 7
Win 8.1 -> Win 8.1
Win 8.1 -> Win 7
However, when going from Win 7 -> Win 8.1, there's a different interpretation of the key blob.
There's an easy fix to this problem. There is an offset (0x14) that indicates the size of what is defined as a "packed key".
If this size is set 0, the Win 8.1 code will execute a different code path and successfully imports the key blob.
// lpBlob contains the OPAQUEKEYBLOB
*(DWORD *)(lpBlob + 0x14) = 0; // Set the packed key length to zero
bResult = CryptImportKey(hProv, lpBlob, dwBlobLength, 0, CRYPT_EXPORTABLE, &hKey);
if (bResult == FALSE)
{
// Import failed
}
// Decrypt the data
bResult = CryptDecrypt(hKey, 0, TRUE, 0, lpCypherText, &dwCypherTextLength);
if (bResult == FALSE)
{
// Decryption failed
}
// Decryption succeeded