Download EaseFilter Encryption Filter Driver SDK Setup File Download EaseFilter Encryption Filter Driver SDK Zip File
File encryption is the process of converting data in a file into a secret code to protect the data. It is a security measure that ensures that only authorized users can access the data in the file. Encryption is used to protect sensitive information such as personal data, financial information, and confidential business data from unauthorized access . Encrypt file in C++ is complex, the EEFD SDK provides a complete modular framework for the developers to build the file encryption software.
Types of Cryptography: There are two types of cryptography:
- Symmetric Cryptography: It is an encryption system where the sender and receiver of a message use a single common key to encrypt and decrypt messages. Symmetric Key Systems are faster and simpler, but the sender and receiver have to somehow exchange keys securely. The most popular symmetric-key cryptography system is Data Encryption System(DES).
- Asymmetric Cryptography: Under this system, a pair of keys is used to encrypt and decrypt information. A public key is used for encryption and a private key is used for decryption. The public key and the private key are different. Even if the public key is known by everyone, the intended receiver can only decode it because he alone knows the private key.
To encrypt file with C++, there are many C++ encryption libraries available for the programming. Some of the popular ones include:
- Crypto++ Library: A free C++ class library of cryptographic schemes that contains the following algorithms: AES, DES, 3DES, Blowfish, Twofish, Serpent, IDEA, RC2, RC5, RC6, CAST-256, Camellia, SEED, Skipjack, SHACAL-2, Tiger, Whirlpool, RIPEMD, MD2, MD4, MD5, SHA-1, SHA-2, SHA-3, Keccak, Skein, and BLAKE2.
- Aes256: A library written in C++ that offers AES 256 bit encryption and decryption. It uses a salt to extend the encryption key to 256 bit. The encrypted stream is aware of this salt and of the padding added to complete the last encryption block
- OpenSSL: A software library for applications that provide secure communications over computer networks against eavesdropping or need to identify the party at the other end. It supports the ciphers: AES, Blowfish, Camellia, Chacha20, Poly1305, SEED, CAST-128, DES, IDEA, RC2, RC4, RC5, Triple DES, GOST 28147-89,SM4.
- Botan: A cryptography toolkit that aims to be the best option for cryptography in C++ by offering the tools necessary to implement a range of practical systems, such as TLS protocol, X.509 certificates, modern AEAD ciphers, PKCS#11 and TPM hardware support, password hashing, and post quantum crypto schemes
- CNG: A Cryptography API has been released since Windows Vista. The Next Generation (CNG) is a cryptographic API that you can use to create encryption security software for encryption key management, cryptography and data security, and cryptography and network security. CNG allows you to encrypt data by using a minimum number of function calls and allows you to perform all of the memory management. While many of the protocol implementation details are left up to the user, CNG provides the primitives that perform the actual data encryption and decryption tasks. CNG is validated to Federal Information Processing Standards (FIPS) 140-2 and is part of the Target of Evaluation for the Windows Common Criteria certification.
The C++ Auto Encryption Code Snippet with EEFD
Even though there are a lot of C++ encryption libraries available in the market, but it is still very complex to encrypt file in C++. The EEFD is a mature commercial encryption SDK. It provides a complete modular framework for the developers even without much encryption development experience to build the on-access file encryption software within a day.
EaseFilter Encryption Filter Driver (EEFD) is a file system encryption filter driver. It provides a comprehensive security solution to develop the transparent on-access file level encryption products. The EEFD allows you to encrypt the newly created files transparently. You can authorize the on-access encryption/decryption under the control of client-defined policy.
The below code snippet demonstrates how to setup a filter rule to encrypt the file transparently in an encryption folder with EEFD SDK, only the authorized processes and users can read the encrypted file, the unauthorized processes or users will get the raw encrypted data.
DWORD threadCount = 5;
DWORD connectionTimeout = 20; //SECONDS
FilterControl* filterControl = FilterControl::GetSingleInstance();
FileFilterRule fileFilterRule(L"c:\\encryptFolder\\*");
fileFilterRule.AccessFlag = ALLOW_MAX_RIGHT_ACCESS|ENABLE_FILE_ENCRYPTION_RULE;
//if you have a master key, you can set it here, or if you want to get the encryption key from the callback function then don't set the key here.
//256 bit,32bytes encrytpion key
unsigned char key[] = {0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe,0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81,0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7,0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4};
if(!fileFilterRule.set_EncryptionKey(key,sizeof(key)))
{
goto Exit;
}
//get raw encrypted data access rights.
ULONG rawEncryptionRights = accessFlag & (~ALLOW_READ_ENCRYPTED_FILES);
//disable the explorer to read encrypted file, explorer will get the raw encrypted data.
//so you can copy the encrypted file to other place in Windows explorer, the file will be kept encrypted.
//this feature requires the process filter driver feature, it need to enable the process filter driver.
ULONG filterType = FILE_SYSTEM_ENCRYPTION|FILE_SYSTEM_PROCESS;
fileFilterRule.AddAccessRightsToProcessName(L"explorer.exe", rawEncryptionRights);
filterControl->AddFileFilter(fileFilterRule);
filterControl->StartFilter(filterType,threadCount,connectionTimeout,registerKey);
_tprintf(_T("\n\nStart Encryption for folder %ws,\r\nThe new created file will be encrypted, the encrypted file can be decrypted automatically in this folder\
.\r\n Press any key to stop the filter driver.\n"),fileFilterMask);
system("pause");
getchar();
filterControl->StopFilter();
delete filterControl;
C++ Encrypting Data Example With CNG
The following example shows how to encrypt data with CNG by using the advanced encryption standard (AES) symmetric encryption algorithm.
#include windows.h
#include stdio.h
#include bcrypt.h
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#define DATA_TO_ENCRYPT "Test Data"
const BYTE rgbPlaintext[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
static const BYTE rgbIV[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
static const BYTE rgbAES128Key[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
void PrintBytes(
IN BYTE *pbPrintData,
IN DWORD cbDataLen)
{
DWORD dwCount = 0;
for(dwCount=0; dwCount < cbDataLen;dwCount++) { printf("0x%02x, ",pbPrintData[dwCount]); if(0 == (dwCount + 1 )%10) putchar('\n'); } } void __cdecl wmain( int argc, __in_ecount(argc) LPWSTR *wargv) { BCRYPT_ALG_HANDLE hAesAlg = NULL; BCRYPT_KEY_HANDLE hKey = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; DWORD cbCipherText = 0, cbPlainText = 0, cbData = 0, cbKeyObject = 0, cbBlockLen = 0, cbBlob = 0; PBYTE pbCipherText = NULL, pbPlainText = NULL, pbKeyObject = NULL, pbIV = NULL, pbBlob = NULL; UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(wargv); // Open an algorithm handle. if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( &hAesAlg, BCRYPT_AES_ALGORITHM, NULL, 0))) { wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); goto Cleanup; } // Calculate the size of the buffer to hold the KeyObject. if(!NT_SUCCESS(status = BCryptGetProperty( hAesAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(DWORD), &cbData, 0))) { wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status); goto Cleanup; } // Allocate the key object on the heap. pbKeyObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbKeyObject); if(NULL == pbKeyObject) { wprintf(L"**** memory allocation failed\n"); goto Cleanup; } // Calculate the block length for the IV. if(!NT_SUCCESS(status = BCryptGetProperty( hAesAlg, BCRYPT_BLOCK_LENGTH, (PBYTE)&cbBlockLen, sizeof(DWORD), &cbData, 0))) { wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status); goto Cleanup; } // Determine whether the cbBlockLen is not longer than the IV length. if (cbBlockLen > sizeof (rgbIV))
{
wprintf (L"**** block length is longer than the provided IV length\n");
goto Cleanup;
}
// Allocate a buffer for the IV. The buffer is consumed during the
// encrypt/decrypt process.
pbIV= (PBYTE) HeapAlloc (GetProcessHeap (), 0, cbBlockLen);
if(NULL == pbIV)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
memcpy(pbIV, rgbIV, cbBlockLen);
if(!NT_SUCCESS(status = BCryptSetProperty(
hAesAlg,
BCRYPT_CHAINING_MODE,
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
sizeof(BCRYPT_CHAIN_MODE_CBC),
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptSetProperty\n", status);
goto Cleanup;
}
// Generate the key from supplied input key bytes.
if(!NT_SUCCESS(status = BCryptGenerateSymmetricKey(
hAesAlg,
&hKey,
pbKeyObject,
cbKeyObject,
(PBYTE)rgbAES128Key,
sizeof(rgbAES128Key),
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGenerateSymmetricKey\n", status);
goto Cleanup;
}
// Save another copy of the key for later.
if(!NT_SUCCESS(status = BCryptExportKey(
hKey,
NULL,
BCRYPT_OPAQUE_KEY_BLOB,
NULL,
0,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptExportKey\n", status);
goto Cleanup;
}
// Allocate the buffer to hold the BLOB.
pbBlob = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbBlob);
if(NULL == pbBlob)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptExportKey(
hKey,
NULL,
BCRYPT_OPAQUE_KEY_BLOB,
pbBlob,
cbBlob,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptExportKey\n", status);
goto Cleanup;
}
cbPlainText = sizeof(rgbPlaintext);
pbPlainText = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbPlainText);
if(NULL == pbPlainText)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
memcpy(pbPlainText, rgbPlaintext, sizeof(rgbPlaintext));
//
// Get the output buffer size.
//
if(!NT_SUCCESS(status = BCryptEncrypt(
hKey,
pbPlainText,
cbPlainText,
NULL,
pbIV,
cbBlockLen,
NULL,
0,
&cbCipherText,
BCRYPT_BLOCK_PADDING)))
{
wprintf(L"**** Error 0x%x returned by BCryptEncrypt\n", status);
goto Cleanup;
}
pbCipherText = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbCipherText);
if(NULL == pbCipherText)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
// Use the key to encrypt the plaintext buffer.
// For block sized messages, block padding will add an extra block.
if(!NT_SUCCESS(status = BCryptEncrypt(
hKey,
pbPlainText,
cbPlainText,
NULL,
pbIV,
cbBlockLen,
pbCipherText,
cbCipherText,
&cbData,
BCRYPT_BLOCK_PADDING)))
{
wprintf(L"**** Error 0x%x returned by BCryptEncrypt\n", status);
goto Cleanup;
}
// Destroy the key and reimport from saved BLOB.
if(!NT_SUCCESS(status = BCryptDestroyKey(hKey)))
{
wprintf(L"**** Error 0x%x returned by BCryptDestroyKey\n", status);
goto Cleanup;
}
hKey = 0;
if(pbPlainText)
{
HeapFree(GetProcessHeap(), 0, pbPlainText);
}
pbPlainText = NULL;
// We can reuse the key object.
memset(pbKeyObject, 0 , cbKeyObject);
// Reinitialize the IV because encryption would have modified it.
memcpy(pbIV, rgbIV, cbBlockLen);
if(!NT_SUCCESS(status = BCryptImportKey(
hAesAlg,
NULL,
BCRYPT_OPAQUE_KEY_BLOB,
&hKey,
pbKeyObject,
cbKeyObject,
pbBlob,
cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGenerateSymmetricKey\n", status);
goto Cleanup;
}
//
// Get the output buffer size.
//
if(!NT_SUCCESS(status = BCryptDecrypt(
hKey,
pbCipherText,
cbCipherText,
NULL,
pbIV,
cbBlockLen,
NULL,
0,
&cbPlainText,
BCRYPT_BLOCK_PADDING)))
{
wprintf(L"**** Error 0x%x returned by BCryptDecrypt\n", status);
goto Cleanup;
}
pbPlainText = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbPlainText);
if(NULL == pbPlainText)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
if(!NT_SUCCESS(status = BCryptDecrypt(
hKey,
pbCipherText,
cbCipherText,
NULL,
pbIV,
cbBlockLen,
pbPlainText,
cbPlainText,
&cbPlainText,
BCRYPT_BLOCK_PADDING)))
{
wprintf(L"**** Error 0x%x returned by BCryptDecrypt\n", status);
goto Cleanup;
}
if (0 != memcmp(pbPlainText, (PBYTE)rgbPlaintext, sizeof(rgbPlaintext)))
{
wprintf(L"Expected decrypted text comparison failed.\n");
goto Cleanup;
}
wprintf(L"Success!\n");
Cleanup:
if(hAesAlg)
{
BCryptCloseAlgorithmProvider(hAesAlg,0);
}
if (hKey)
{
BCryptDestroyKey(hKey);
}
if(pbCipherText)
{
HeapFree(GetProcessHeap(), 0, pbCipherText);
}
if(pbPlainText)
{
HeapFree(GetProcessHeap(), 0, pbPlainText);
}
if(pbKeyObject)
{
HeapFree(GetProcessHeap(), 0, pbKeyObject);
}
if(pbIV)
{
HeapFree(GetProcessHeap(), 0, pbIV);
}
}