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?
Error encrypting with CALG_AES_256
#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.
2 answers
Sort by: Most helpful
-
-
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.
This is the file to be encrypted:
This is the encrypted file after runnning the program:
Exported key blob:
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.