An OPAQUEKEYBLOB exported via CryptExportKey on Windows 7 is incompatible with Windows 8.1

 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