Error encrypting with CALG_AES_256

Angel Gil 0 Reputation points
2023-01-31T23:19:06.1266667+00:00

#include <wincrypt.h>
#include <iostream>
#include <system_error>
#pragma comment(lib, "Crypt32.lib")



unsigned char key[] = "123456789012";
int keylen=sizeof(key);

int AES(const char * data,  int data_len) {
  HCRYPTPROV hProv;
  HCRYPTHASH hHash;
  HCRYPTKEY hKey;
  DWORD len=(DWORD)data_len;
  DWORD size_output_data=(DWORD)data_len;
  BYTE *pBuffer;

  
  if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){
     std::cout<<"failed CryptAcquireContextW";
    return -1;
  }
  if (!CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash)){
     std::cout<<"failed CryptCreateHash";
    return -1;
  }
  if (!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)){
     std::cout<<"failed CryptHashData";
    return -1;
  }
  if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0,&hKey)){
     std::cout<<"failed CryptDeriveKey";
    return -1;
  }

    DWORD size_data=(DWORD)strlen(data);
    DWORD need_size=size_data;
  if(!CryptEncrypt(hKey,0,TRUE,0,NULL,&need_size,0)){
      std::cout<<"failet to get size\n";
      return -1;
  }

  memcpy(pBuffer=(BYTE*)_alloca(need_size),data,size_data);
  if(!CryptEncrypt(hKey,0,TRUE,0,pBuffer,&size_data,need_size)){
    std::cout<<"failed to encrypt\n";
    DWORD error=GetLastError();
    std::cout<<std::system_category().message(error);

    return -1;
  }


  DWORD encrypt_size=(DWORD)strlen(pBuffer);
  if(!CryptDecrypt(hKey,(HCRYPTHASH) NULL,TRUE,0,pBuffer,&encrypt_size)){
    DWORD error=GetLastError();
    std::cout<<"failed to decrypting"<<"\n"<<std::system_category().message(error);
    return -1;
    }
    //memset(pBuffer+pp,0,strlen(pBuffer)); doing this fixes it deletes the bad 
                                            //data, but it doesn't feel right to me to do it
    std::cout<<pBuffer<<"\n";


  CryptReleaseContext(hProv, 0);
  CryptDestroyHash(hHash);
  CryptDestroyKey(hKey);
  

  return strlen(pBuffer);

  }   



int main(){
    

    char toencrypt[] = "d";//This character * 150
    int int_output_en=AES(toencrypt,strlen(toencrypt));
    system("pause");
return 0;
}

Hello, I have the following, error:

I am trying to use AES in c++ with CALG_AES_256, but when decrypting it only overwrites the data, from the encrypted buffer, also if I try to encrypt a buffer of more than 150 characters or less than 100 (although it is passed by varying), it gives an error "Incorrect data ". if i put between that range of characters there is no error problem, but there are still garbage characters. I can fix the junk data with memset, but looking at some examples they don't use it

EX:

THIS IS MY TEXT, HELLO WORLD,

results:

THIS IS MY TEXT, HELLO WORLD!"·$%

(this is a manual example, please do not copy it)

using PROV_RSA_FULL, it doesn't give problems, but the latter is RSA not AES.

Windows development | Windows API - Win32
Developer technologies | C++
{count} votes

2 answers

Sort by: Most helpful
  1. Angel Gil 0 Reputation points
    2023-02-02T03:50:13.62+00:00

    Tong Xu - MSFT I'm still new to aes, so I don't quite understand the multiple of the block size, could you allow me the fixed code please?

    0 comments No comments

  2. Tong Xu - MSFT 2,546 Reputation points Microsoft External Staff
    2023-02-02T08:07:54.37+00:00

    Hi, @Angel Gil
    Welcome to Microsoft Q&A!
    It is recommended to refer to the official Microsoft documentation. Please forgive me for making huge changes in the code.
    The following example encrypts a data file.
    So I wrote a program based on that document. It can encrypt a txt file, put it into a file and export the key.
    It runs well.
    encry cmd

    This is the file to be encrypted:
    hello1

    This is the encrypted file after runnning the program:
    hello2

    Exported key blob:
    key

    Here is the code:
    The top defines the minimum unit length of each encrypted block and the algorithm used to generate the key.

    #include<windows.h>
    #include <iostream>
    #include<wincrypt.h>
    #include<string>
    #include<vector>
    #include <system_error>
    #pragma comment(lib, "Advapi32.lib")
    
    
    
    #include <tchar.h>
    #include <stdio.h>
    
    #include <conio.h>
    
    
    #define KEYLENGTH  0x00800000   //Length and type of generated key
    #define ENCRYPT_ALGORITHM CALG_RC4 //The algorithm used to generate the key
    #define ENCRYPT_BLOCK_SIZE 8 //Minimum unit length of each encrypted data block
    bool fEOF = FALSE;
    bool MyEncryptFile(
        LPTSTR szSource,
        LPTSTR szDestination,
        LPTSTR szPassword,
        LPTSTR szexportkey);
    
    void MyHandleError(
        LPTSTR psz,
        int nErrorNumber);
    
    int main()
    {
    
        LPTSTR pszSource = (LPTSTR)"C:\\hello1.txt";//Files to be encrypted
        LPTSTR pszDestination = (LPTSTR)"C:\\hello2.txt";//v
        LPTSTR pszexportkeyDestination = (LPTSTR)"C:\\exportkeyblob.txt";
        //LPTSTR pszPassword = (LPTSTR)"123456";//Any string of characters for encryption and decryption
        LPTSTR pszPassword = NULL;
        //---------------------------------------------------------------
        // Call EncryptFile to do the actual encryption.
        if (MyEncryptFile(pszSource, pszDestination, pszPassword, pszexportkeyDestination))
        {
            _tprintf(TEXT("Encryption of the file %s was successful. \n"), pszSource);
            _tprintf(TEXT("The encrypted data is in file %s.\n"), pszDestination);
        }
        else
        {
            MyHandleError((LPTSTR)TEXT("Error encrypting file!\n"), GetLastError());
        }
        getchar();
        return 0;
    }
    
    bool MyEncryptFile(LPTSTR pszSourceFile, LPTSTR pszDestinationFile, LPTSTR pszPassword, LPTSTR pszexportkeyDestination)
    {
        bool fReturn = false;
        HANDLE hSourceFile = INVALID_HANDLE_VALUE;
        HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
        HANDLE hexportkeyDestinationFile = INVALID_HANDLE_VALUE;
    
        HCRYPTPROV hCryptProv = NULL;
        HCRYPTKEY hKey = NULL;
        HCRYPTKEY hXchgKey = NULL;
        HCRYPTHASH hHash = NULL;
    
        PBYTE pbKeyBlob = NULL;
        DWORD dwKeyBlobLen;
    
        PBYTE pbBuffer = NULL;
        DWORD dwBlockLen;
        DWORD dwBufferLen;
        DWORD dwCount;
    
    
        hSourceFile = CreateFileA(
            pszSourceFile,
            FILE_READ_DATA,
            FILE_SHARE_READ,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL);
        if (INVALID_HANDLE_VALUE != hSourceFile)
        {
            _tprintf(TEXT("The source plaintext file, %s, is open. \n"), pszSourceFile);
        }
        else
        {
            MyHandleError((LPTSTR)TEXT("Error opening source plaintext file!\n"), GetLastError());
            goto Exit_MyEncryptFile;
        }
    
        // createfile
        hDestinationFile = CreateFile(pszDestinationFile, FILE_WRITE_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (INVALID_HANDLE_VALUE != hDestinationFile)
        {
            _tprintf(TEXT("The destination file, %s, is open. \n"), pszDestinationFile);
        }
        else
        {
            MyHandleError((LPTSTR)TEXT("Error opening destination file!\n"), GetLastError());
            goto Exit_MyEncryptFile;
        }
        //obtain container handle
        if (!CryptAcquireContext(
            &hCryptProv, 
            NULL,   
            MS_ENHANCED_PROV, 
            PROV_RSA_FULL, //Encryption policy used
            0))
        {
            //
            if (GetLastError() == NTE_BAD_KEYSET)
            {
                if (!CryptAcquireContext(
                    &hCryptProv,
                    NULL,
                    MS_ENHANCED_PROV,
                    PROV_RSA_FULL,
                    CRYPT_NEWKEYSET)) 
                {
                    MyHandleError((LPTSTR)TEXT("Error during CryptAcquireContext!\n"), GetLastError());
                    goto Exit_MyEncryptFile;
                    //return FALSE;
                }
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error during CryptAcquireContext!\n"), GetLastError());
                goto Exit_MyEncryptFile;
                //return FALSE;
            }
        }
        _tprintf(TEXT("A cryptographic provider has been acquired. \n"));
    
        // Create key
        if (pszPassword == NULL)
        {
            // If pszPassword is NULL, a random key is generated, and then the random key is written to the file
           
            if (CryptGenKey( 
                hCryptProv,
                ENCRYPT_ALGORITHM,  
                KEYLENGTH | CRYPT_EXPORTABLE, 
                &hKey))
            {
                _tprintf(TEXT("A session key has been created. \n"));
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error during CryptGenKey. \n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
    
            //-----------------------------------------------------------
            // Get the handle to the exchange public key. 
            
            if (CryptGetUserKey(
                hCryptProv,
                AT_KEYEXCHANGE, 
                &hXchgKey)) 
            {
                _tprintf(TEXT("The user public key has been retrieved. \n"));
            }
            else
            {
                if (NTE_NO_KEY == GetLastError())
                {
                    
                    if (!CryptGenKey(
                        hCryptProv,
                        AT_KEYEXCHANGE,
                        CRYPT_EXPORTABLE,
                        &hXchgKey))
                    {
                        MyHandleError((LPTSTR)TEXT("Could not create a user public key.\n"), GetLastError());
                        goto Exit_MyEncryptFile;
                    }
                }
                else
                {
                    MyHandleError((LPTSTR)TEXT("User public key is not available and may ")TEXT("not exist.\n"), GetLastError());
                    goto Exit_MyEncryptFile;
                }
            }
    
            //-----------------------------------------------------------
            // Determine size of the key BLOB, and allocate memory. 
            
            if (CryptExportKey(
                hKey, 
                hXchgKey, 
                SIMPLEBLOB, 
                0,
                NULL, 
                &dwKeyBlobLen))
            {
                _tprintf(TEXT("The key BLOB is %d bytes long. \n"), dwKeyBlobLen);
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error computing BLOB length! \n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
            
            if (pbKeyBlob = (BYTE*)malloc(dwKeyBlobLen))
            {
                _tprintf(TEXT("Memory is allocated for the key BLOB. \n"));
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Out of memory. \n"), E_OUTOFMEMORY);
                goto Exit_MyEncryptFile;
            }
    
            //-----------------------------------------------------------
            // Encrypt and export the session key into a simple key 
            // BLOB.
            
            if (CryptExportKey(
                hKey,
                hXchgKey,
                SIMPLEBLOB,
                0,
                pbKeyBlob,
                &dwKeyBlobLen))
            {
                _tprintf(TEXT("The key has been exported. \n"));
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error during CryptExportKey!\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
    
            //-----------------------------------------------------------
            // Release the key exchange key handle. 
            
            if (hXchgKey)
            {
                if (!(CryptDestroyKey(hXchgKey)))
                {
                    MyHandleError(
                        (LPTSTR)TEXT("Error during CryptDestroyKey.\n"),
                        GetLastError());
                    goto Exit_MyEncryptFile;
                }
    
                hXchgKey = 0;
            }
            hexportkeyDestinationFile = CreateFile(pszexportkeyDestination, FILE_WRITE_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
            if (INVALID_HANDLE_VALUE != hexportkeyDestinationFile)
            {
                _tprintf(TEXT("The destination file, %s, is open. \n"), pszexportkeyDestination);
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error opening destination file!\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
            
            if (!WriteFile(
                hexportkeyDestinationFile,
                &dwKeyBlobLen,
                sizeof(DWORD),
                &dwCount,
                NULL))
            {
                MyHandleError((LPTSTR)TEXT("Error writing header.\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
            else
            {
                _tprintf(TEXT("A file header has been written. \n"));
            }
            //keyblob
            if (!WriteFile(
                hexportkeyDestinationFile,
                pbKeyBlob,
                dwKeyBlobLen,
                &dwCount,
                NULL))
            {
                MyHandleError((LPTSTR)TEXT("Error writing header.\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
            else
            {
                _tprintf(TEXT("The key BLOB has been written to the ")TEXT("file. \n"));
            }
            // Free memory.
            free(pbKeyBlob);
        }
        else
        {
            //-----------------------------------------------------------
            // The file will be encrypted with a session key derived 
            // from a password.
            // The session key will be recreated when the file is 
            // decrypted only if the password used to create the key is 
            // available. 
    
            
            if (CryptCreateHash( 
                hCryptProv,
                CALG_MD5, 
                0,
                0,
                &hHash))
            {
                _tprintf(TEXT("A hash object has been created. \n"));
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error during CryptCreateHash!\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
    
            
            if (CryptHashData( 
                hHash,
                (BYTE*)pszPassword,
                lstrlen(pszPassword),
                0))
            {
                _tprintf(TEXT("The password has been added to the hash. \n"));
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error during CryptHashData. \n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
    
            
            if (CryptDeriveKey(  
                hCryptProv,
                ENCRYPT_ALGORITHM, 
                hHash, 
                KEYLENGTH, 
                &hKey)) 
            {
                _tprintf(TEXT("An encryption key is derived from the ")TEXT("password hash. \n"));
            }
            else
            {
                MyHandleError((LPTSTR)TEXT("Error during CryptDeriveKey!\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
        }
    
        //---------------------------------------------------------------
        // The session key is now ready. If it is not a key derived from 
        // a  password, the session key encrypted with the private key 
        // has been written to the destination file.
    
        //---------------------------------------------------------------
        // Determine the number of bytes to encrypt at a time. 
        // This must be a multiple of ENCRYPT_BLOCK_SIZE.
        
        dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
    
        //---------------------------------------------------------------
        // Determine the block size. If a block cipher is used, 
        // it must have room for an extra block. 
        if (ENCRYPT_BLOCK_SIZE > 1)
        {
            dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
        }
        else
        {
            dwBufferLen = dwBlockLen;
        }
    
        //---------------------------------------------------------------
        // Allocate memory. 
        if (pbBuffer = (BYTE*)malloc(dwBufferLen))
        {
            _tprintf(TEXT("Memory has been allocated for the buffer. \n"));
        }
        else
        {
            MyHandleError((LPTSTR)TEXT("Out of memory. \n"), E_OUTOFMEMORY);
            goto Exit_MyEncryptFile;
        }
    
        //---------------------------------------------------------------
        // In a do loop, encrypt the source file, 
        // and write to the source file. 
       
        do
        {
            //-----------------------------------------------------------
            // Read up to dwBlockLen bytes from the source file. 
            
            if (!ReadFile(
                hSourceFile, 
                pbBuffer,
                dwBlockLen, 
                &dwCount, 
                NULL))
            {
                MyHandleError((LPTSTR)TEXT("Error reading plaintext!\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
    
            if (dwCount < dwBlockLen)
            {
                fEOF = TRUE;
            }
            
            if (!CryptEncrypt(
                hKey,
                NULL,
                fEOF, 
                0,
                pbBuffer,
                &dwCount,
                dwBufferLen))
            {
                MyHandleError((LPTSTR)TEXT("Error during CryptEncrypt. \n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
            
            if (!WriteFile(
                hDestinationFile,
                pbBuffer,
                dwCount,
                &dwCount,
                NULL))
            {
                MyHandleError((LPTSTR)TEXT("Error writing ciphertext.\n"), GetLastError());
                goto Exit_MyEncryptFile;
            }
        } 
        while (!fEOF);
        
    
         fReturn = true;
    
        Exit_MyEncryptFile:
            //---------------------------------------------------------------
            // Close files.
            if (hSourceFile)
            {
                CloseHandle(hSourceFile);
            }
    
            if (hDestinationFile)
            {
                CloseHandle(hDestinationFile);
            }
    
            //---------------------------------------------------------------
            // Free memory. 
            if (pbBuffer)
            {
                free(pbBuffer);
            }
    
    
            //-----------------------------------------------------------
            // Release the hash object. 
            if (hHash)
            {
                if (!(CryptDestroyHash(hHash)))
                {
                    MyHandleError(
                        (LPTSTR)TEXT("Error during CryptDestroyHash.\n"),
                        GetLastError());
                }
    
                hHash = NULL;
            }
    
            //---------------------------------------------------------------
            // Release the session key. 
            if (hKey)
            {
                if (!(CryptDestroyKey(hKey)))
                {
                    MyHandleError(
                        (LPTSTR)TEXT("Error during CryptDestroyKey!\n"),
                        GetLastError());
                }
            }
    
            //---------------------------------------------------------------
            // Release the provider handle. 
            if (hCryptProv)
            {
                if (!(CryptReleaseContext(hCryptProv, 0)))
                {
                    MyHandleError(
                        (LPTSTR)TEXT("Error during CryptReleaseContext!\n"),
                        GetLastError());
                }
            }
            return fReturn;
        } // End Encryptfile.
    
    
    //-------------------------------------------------------------------
    //  This example uses the function MyHandleError, a simple error
    //  handling function, to print an error message to the  
    //  standard error (stderr) file and exit the program. 
    //  For most applications, replace this function with one 
    //  that does more extensive error reporting.
    
    void MyHandleError(LPTSTR psz, int nErrorNumber)
    {
        _ftprintf(stderr, TEXT("An error occurred in the program. \n"));
        _ftprintf(stderr, TEXT("%s\n"), psz);
        _ftprintf(stderr, TEXT("Error number %x.\n"), nErrorNumber);
    }
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.