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 API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,427 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,540 questions
{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 1,511 Reputation points Microsoft Vendor
    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.