Protect your data with DPAPI
We already know that the use of Win32API functions EncryptFile and DecryptFile can be easily encrypted. However, these two functions are contacted with the system account, whether to decrypt to completely see if there is a higher permissions, and the user's data is actually not protected. A more flexible data protection method will be described below.
Starting with Win2000, the operating system begins to provide a data protection interface called Data Protection API (DPAPI). This interface has two functions that provide system-level data protection services. These two functions exist in the Crypt32.dll library, part of Cryptapi, but use more than other Cryptapi functions than other CryptAPI functions.
DPAPI can implement a password-based data encryption and decryption. That is to say, we provide a password for encryption, while others only know this password can be decrypted. In fact, the DPAPI has completed fairly complex encrypted decryption operations in the background, including the generation, storage, usage of the key. This article only wants to introduce how to use DPAPI, this will not discuss its internal mechanism.
DPAPI encryption function
Bool WinAPI Cryptprotectdata
[In] data_blob * pdatain, // input data, clear text
[In] lpcwstr szdatadescr, // Description information
[In] data_blob * POPTIONALENTROPY, // Additional protection information
[In] pvoid pvroid, // Reserved parameters, must be NULL
[In] cryptprotect_promptstruct * ppromptstruct, // Tips dialog box structure
DWORD DWFLAGS, // Sign
[OUT] DATA_BLOB * PDATAOUT // Output Data, Ciphertext
);
Entering data parameters pDatain is a Data_Blob structure that is defined as follows:
TypedEf struct _cryptoAPi_blob {
DWORD CBDATA; // Data length
BYTE * PBDATA; / / Pointer to point to data
} DATA_BLOB;
The parameter szdatadescr is a string, which may be any information about encryption or other information, but cannot be NULL, which will exist in the final output ciphertext data in a clear manner.
Parameters POPTIONALENTROPY is used in additional password protection, which will be described in detail later.
Parameters PPROMPTSTRUCT is used to specify a secure prompt dialog that the dialog will pop up when the dialog prompts the user in progress. If this parameter is NULL, the dialog is not popped. This is not a detailed definition of the CryptProtect_PromptSTRUCT structure, you can review the relevant content of MSDN. The rear program will set this parameter to null;
Parameters dwflags are some options for encryption, which is usually set to 0, detailed description, see the relevant content of MSDN;
The parameter pData is output data, which is also a DATA_BLOB structure, but it should be noted that the memory pointed by pDataout-> PBData is allocated by the system, and the memory should be released with the localfree function after using the output data.
DPAPI decryption function
BOOL WINAPI CRYPTUNPROTECTDATA ([in] data_blob * pdatain, // input data, ciphertext
[OUT] lpcwstr * ppszdatadescr, // output description information
[In] data_blob * POPTIONALENTROPY, // Additional protection information
[In] pvoid pvroid, // Reserved parameters, must be NULL
[In] cryptprotect_promptstruct * ppromptstruct, // Tips dialog box structure
DWORD DWFLAGS, // Sign
[OUT] data_blob * pdataout // Output data, clear text
);
The parameters of the decryption function are substantially similar to the parameters of the encryption function. The only thing to indicate that the parameter PPSZDATESCR should be specified as a pointer variable. After the decryption is complete, the variable will point to the description information specified when encrypted, and finally use the LocalFree function. Release the string. If you don't want to get a description, you can set this parameter to NULL.
DPAPI and system account contact is still very close, he automatically uses the current user's system login password as an encryption password, so that all programs of the same machine can decrypt data encrypted by other programs. To prevent this, the function provides the POPTIONALENTROPY parameter so that we have the opportunity to use your own password. If the POPTIONALENTROPY parameter is provided, the DPAPI will use the current user system login password and the combination of additional protection passwords we provide. If you don't want to use additional password protection, you can set this parameter null.
Because DPAPI uses the user account to contact, the data encrypted on a machine generally cannot decrypt on another machine (see MSDN related content).
The following program uses the DPAPI to implement the file encryption and decryption, where password is optional, but if you use Password when encryption, you must provide the same password ..
/ ************************************************** *******
* DPAPI.exe
* Encrypt and Decrypt File
* Wrote by WABC on 2002-5-20
*********************************************************** ****** /
#include
#include
DWORD MyEncryptFile (LPCSTR FileName, LPCSTR OUTPUTFILENAME, LPCSTR Password);
DWORD MyDecryptfile (LPCSTR FileName, LPCSTR OUTPUTFILENAME, LPCSTR PASSWORD);
Void Printusage ();
Int main (int Argc, char * argv [])
{
// Command Line: DPAPI
IF (Argc <4 || Argc> 5) {
PRINTUSAGE ();
Return 0;
}
Char * filename = argv [2];
Char * OutputFileName = argv [3]; char * password = null;
IF (argc == 5) Password = argv [4];
DWORD RC = 0;
IF (Argv [1] [0] == 'E') {// encrypt
Rc = MyEncryptfile (filename, outputfilename, password);
IF (rc! = 0) {
Printf ("Can't Encrypt the File '% S', Error Code:% D. / N", FileName, RC);
Return 0;
}
Printf ("Encrypt SuccessFully! / N");
Else {// Decrypt
Rc = MyDecryptfile (filename, outputfilename, password);
IF (rc! = 0) {
Printf ("Can't Decrypt The File '% S', Error Code:% D. / N", FileName, RC);
Return 0;
}
Printf ("Decrypt SuccessFully! / N");
}
Return 0;
}
// Encrypt Function
DWORD MyEncryptfile (LPCSTR FileName, LPCSTPUTFILENAME, LPCSTPASWORD)
{
Handle Hfile = NULL;
DWORD filelen = 0;
BYTE * fileData = null;
Data_blob datain;
Data_blob dataout;
Data_blob datapwd;
Data_blob * pdatapwd = null;
ZeromeMory (& DataIn, Sizeof);
ZeromeMory (& DataOut, Sizeof);
ZeromeMory (& DataPwd, Sizeof);
IF (Password! = null) {
DataPwd.cbdata = Strlen (Password);
DataPwd.pbdata = (byte *) Password;
PDATAPWD = & DataPwd;
}
Try {
Hfile = cretefile (filename, generic_read, 0, null, open_existing, file_attribute_normal, null);
IF (hfile == invalid_handle_value) ""
Filelen = GetFileSize (HFILE, NULL);
FileData = new byte [filelen];
IF (FileData == Null) Throw ""
Readfile (HFile, FileData, Filelen, & Filelen, NULL);
CloseHandle (HFILE);
Hfile = NULL;
Datain.pbdata = filedata;
Datain.cbdata = filelen;
IF (! CryptProtectData)
& Datain,
L "this is the description string.", // a description start.
PDATAPWD, // Optional Entropy NOT USED.NULL, // RESERVED.
NULL, // Pass a promptstruct.
0,
& DataOut))
{
""
}
DELETE [] FileData;
FileData = NULL;
Hfile = Createfile (OutputFileName, Generic_Write, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
IF (hfile == invalid_handle_value) ""
Writefile (Hfile, DataOut.pbdata, DataOut.cbdata, & Filelen, NULL);
CloseHandle (HFILE);
Hfile = NULL;
Localfree (DataOut.pbdata);
ZeromeMory (& DataOut, Sizeof
} catch (...) {
IF (HFile) CloseHandle (HFILE);
IF (FileData) delete [] FileData;
IF (DataOut.pbdata) LocalFree (DataOut.pbdata);
Return getLastError ();
}
Return 0;
}
// Decrypt Function
DWORD MyDecryptfile (LPCSTR FileName, LPCSTR OUTPUTFILENAME, LPCSTR PASSWORD)
{
Handle Hfile = NULL;
DWORD filelen = 0;
BYTE * fileData = null;
Data_blob datain;
Data_blob dataout;
Data_blob datapwd;
Data_blob * pdatapwd = null;
ZeromeMory (& DataIn, Sizeof);
ZeromeMory (& DataOut, Sizeof);
ZeromeMory (& DataPwd, Sizeof);
IF (Password! = null) {
DataPwd.cbdata = Strlen (Password);
DataPwd.pbdata = (byte *) Password;
PDATAPWD = & DataPwd;
}
Try {
Hfile = cretefile (filename, generic_read, 0, null, open_existing, file_attribute_normal, null);
IF (hfile == invalid_handle_value) ""
Filelen = GetFileSize (HFILE, NULL);
FileData = new byte [filelen];
IF (FileData == Null) Throw ""
Readfile (HFile, FileData, Filelen, & Filelen, NULL);
CloseHandle (HFILE);
Hfile = NULL;
Datain.pbdata = filedata;
Datain.cbdata = filelen;
IF (! CryptunprotectData)
& Datain, NULL,
PDataPwd, // Optional Entropy
Null, // reserved
Null, // Optional Promptstruct
0,
& DataOut))
{
""
}
DELETE [] FileData;
FileData = NULL;
Hfile = Createfile (OutputFileName, Generic_Write, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
IF (hfile == invalid_handle_value) ""
Writefile (Hfile, DataOut.pbdata, DataOut.cbdata, & Filelen, NULL);
CloseHandle (HFILE);
Hfile = NULL;
Localfree (DataOut.pbdata);
ZeromeMory (& DataOut, Sizeof
} catch (...) {
IF (HFile) CloseHandle (HFILE);
IF (FileData) delete [] FileData;
IF (DataOut.pbdata) LocalFree (DataOut.pbdata);
Return getLastError ();
}
Return 0;
}
Void Printusage ()
{
Printf ("USAGE: DPAPI
Printf ("e Encrypt file / n");
Printf ("D D Decrypt File / N);
}
To compile the above programs, you must first download a Platfromsdk (because there is no function description of the DPAPI in the Crypt32.lib export library with the VC, but there is a DPAPI function in the CRYPT32.DLL of the operating system), then put the Crypt32 in PlatformSDK. .lib joins your VC project, and finally add macro defined #define _win32_winnt 0x500 in stdafx.h in the VC project.
Use DPAPI to pay attention to the following:
1. Encryption and decryption operations must be carried out on the same computer;
2. If additional password protection is provided, the same password must be provided when decrypting;
3. After the DPAPI function, be sure to remember the memory allocated with the LocalFree function release system;
4, DPAPI does not store data mechanism, the application must be responsible for storing encrypted or decrypted data.