Click here to Skip to main content
15,888,351 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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;
 
    // 获得默认provider句柄.
    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) //  Object already exists.
			{
				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))
            {
                // CryptGenKey发生错误!
                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; 
 
    // 获取默认密钥blob大小, 并分配内存.
    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;
    }
 

 
    // 将密钥导出到简单密钥blob.
    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;
    }
 
    // 输出长度、密钥blob、分配内存
    *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);
 
    // 释放provider句柄.
    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;
 
    //unsigned char* buffer = new unsigned char[256];
    //unsigned int iLen = 0;
    //CryptCString( _T("t"), buffer, iLen);

    // 获得默认provider句柄.
    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 )
        {		
            // There is a container but no key - Create an encryption key pair
            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;
    }
 
    // 从源数据中取得密钥blob长度
    // 并初始化指针
    memcpy(&dwBlobLen, pIn, sizeof(DWORD));
    pbKeyBlob = (BYTE *)&pIn[sizeof(DWORD)];
 
    // 将密钥blob导入CSP.
    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);
 
    // 释放provider句柄.
    if(hProv != 0) CryptReleaseContext(hProv, 0);
 
    return TRUE;
}
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900