I used the crypto API to encrypt/decrypt a file, but have a problem.
On some computer, decrypt fails, especially when the system just start up。
I find the call CryptImportKey fails, and the error code is NTE_BAD_DATA。
Could someone give me a help?
Here is my code.
BOOL CUserCrypt::Crypt(unsigned char *pIn, long *plSize, unsigned char **ppOut)
{
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hXchgKey = 0;
DWORD dwCount, dwNewBufLen;
BYTE *pbKeyBlob = NULL;
DWORD dwBlobLen;
if(!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0))
{
if (!CryptAcquireContext( &hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
DWORD dwLastErr = ::GetLastError();
if(0x8009000F == dwLastErr)
{
if(!CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_DELETEKEYSET))
{
return FALSE;
}
else
{
if(!CryptAcquireContext(&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
return FALSE;
}
}
}
}
}
if (!CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey))
{
if (NTE_NO_KEY==GetLastError())
{
if (!CryptGenKey(hProv,AT_KEYEXCHANGE,0,&hKey))
{
CryptReleaseContext(hProv, 0);
return FALSE;
}
else
{
CryptDestroyKey(hKey);
CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hXchgKey);
}
}
else
return FALSE;
}
if (!CryptGenKey(hProv, CALG_RC2, CRYPT_EXPORTABLE, &hKey))
return FALSE;
if (!CryptExportKey( hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwBlobLen))
{
if( hProv != NULL){
CryptReleaseContext(hProv, 0);
}
return FALSE;
}
if (NULL == (pbKeyBlob = (unsigned char *)malloc(dwBlobLen)) ){
if( hProv != NULL){
CryptReleaseContext(hProv, 0);
}
if( hKey != NULL ){
CryptDestroyKey( hKey );
}
return FALSE;
}
if (!CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwBlobLen))
{
if( hProv != NULL){
CryptReleaseContext(hProv, 0);
}
if( hKey != NULL ){
CryptDestroyKey( hKey );
}
free(pbKeyBlob);
return FALSE;
}
dwCount = *plSize;
if (!CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwCount, 0)){
if( hProv != NULL){
CryptReleaseContext(hProv, 0);
}
if( hKey != NULL ){
CryptDestroyKey( hKey );
}
if(hXchgKey != NULL ){
CryptDestroyKey(hXchgKey);
}
free(pbKeyBlob);
return FALSE;
}
*ppOut = (unsigned char *)malloc(sizeof(dwBlobLen) + dwBlobLen + dwCount);
if (!*ppOut)
{
if( hProv != NULL){
CryptReleaseContext(hProv, 0);
}
if( hKey != NULL ){
CryptDestroyKey( hKey );
}
if(hXchgKey != NULL ){
CryptDestroyKey(hXchgKey);
}
free(pbKeyBlob);
return FALSE;
}
memcpy(*ppOut, &dwBlobLen, sizeof(dwBlobLen));
memcpy(&(*ppOut)[sizeof(dwBlobLen)], pbKeyBlob, dwBlobLen);
free(pbKeyBlob);
pbKeyBlob = NULL;
memcpy(&(*ppOut)[sizeof(dwBlobLen)+dwBlobLen], pIn, *plSize);
dwNewBufLen = dwCount;
dwCount = *plSize;
BOOL bSuccess = FALSE;
if ( CryptEncrypt(hKey,
0,
TRUE,
0,
&(*ppOut)[sizeof(dwBlobLen)+dwBlobLen],
&dwCount,
dwNewBufLen)){
bSuccess = TRUE;
}
*plSize = sizeof(dwBlobLen) + dwBlobLen + dwCount;
if(hKey != 0) CryptDestroyKey(hKey);
if(hXchgKey != 0) CryptDestroyKey(hXchgKey);
if(hProv != 0) CryptReleaseContext(hProv, 0);
return bSuccess;
}
BOOL CUserCrypt::Decrypt(unsigned char *pIn, long *plSize)
{
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
HCRYPTKEY hXchgKey = 0;
DWORD dwCount;
BYTE *pbKeyBlob = NULL;
DWORD dwBlobLen;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0))
{
LOG_DEBUG(_T("CryptAcquireContext failed, errorcode = %d, Function: %s"), GetLastError(), __FUNCTIONW__ );
if( GetLastError() == NTE_BAD_KEYSET)
{
if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET) )
{
LOG_DEBUG(_T("CryptAcquireContext failed again, errorcode = %d, Function: %s"), GetLastError(), __FUNCTIONW__ );
return FALSE;
}
}
else
{
return FALSE;
}
}
if( !CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey) )
{
LOG_DEBUG(_T("CryptGetUserKey failed, errorcode = %d, Function: %s"), GetLastError(), __FUNCTIONW__ );
if( GetLastError() == NTE_NO_KEY )
{
if( !CryptGenKey( hProv, AT_KEYEXCHANGE, 0, &hKey ) )
{
LOG_DEBUG(_T("CryptGenKey failed, errorcode = %d, Function: %s"), GetLastError(), __FUNCTIONW__ );
return FALSE;
}
}
}
if( hKey )
{
CryptDestroyKey( hKey );
hKey = NULL;
}
memcpy(&dwBlobLen, pIn, sizeof(DWORD));
pbKeyBlob = (BYTE *)&pIn[sizeof(DWORD)];
if (!CryptImportKey(hProv, pbKeyBlob, dwBlobLen, 0, 0, &hKey))
{
LOG_DEBUG(_T("CryptImportKey failed, errorcode = %d, Function: %s"), GetLastError(), __FUNCTIONW__ );
CryptReleaseContext(hProv, 0);
return FALSE;
}
dwCount =*plSize - (sizeof(DWORD)+dwBlobLen);
if (!CryptDecrypt(hKey, 0, TRUE, 0, &pIn[sizeof(DWORD)+dwBlobLen], &dwCount))
{
LOG_DEBUG(_T("CryptDecrypt failed, errorcode = %d, Function: %s"), GetLastError(), __FUNCTIONW__ );
return FALSE;
}
memmove(pIn, &pIn[sizeof(DWORD)+dwBlobLen], dwCount);
*plSize = dwCount;
if(hKey != 0) CryptDestroyKey(hKey);
if(hProv != 0) CryptReleaseContext(hProv, 0);
return TRUE;
}