Wrap the Data Protection API
Background
The data protection application programming interface (DPAPI) provides operating
system-level security through encryption and decryption. It exposes two
functions: CryptProtectData, which encrypts a blob of data, and
CryptUnprotectData, which decrypts a blob of data. To get a clear understanding
of DPAPI, see
Windows Data Protection.
Platform Invocation
The DPAPI is implemented in a static library named Crypt32.lib and a dynamic
link library (DLL) named Crypt32.dll. Microsoft .NET code cannot directly
interoporate with unmangaged code in DLLs, so you must create a wrapper for the
functions exposed by the DPAPI. The functions accept two structures as
parameters: DATA_BLOB and CRYPTPROTECT_PROMPTSTRUCT. You must reimplement these
structures in managed code to use them from managed code.
Implementing the structures
The unmanaged DATA_BLOB structure has two members: a pointer to a data stream
and the size of the data stream. To use this structure in managed code, you
must reimplement it. You can implement the structure as follows:
public struct DataBlob
{
public int Size;
public IntPtr Data;
}
The unmanaged CRYPTPROTECT_PROMPTSTRUCT structure has four members: an integer
value specifying the size of the structure, a flags member, a pointer to a
window to display a message, and the message to display. To use this structure
in managed code, you must reimplement. You can implement the structure as
follows:
public struct CryptProtectPromptStruct
{
public int Size;
public int Flags;
public IntPtr Window;
public String Message;
}
Wrapping the Functions
The first step in wrapping functions exposed by unmanaged code is to create a
managed version of the function and add the DllImport attribute. The DllImport
attribute accepts a single required String parameter, which specifies the DLL
file that contains the functions that you are wrapping. For example, you could
use the DllImport attribute as follows:
[DllImport("Crypt32.dll")]
The attribute above expects the method towhich the attribute is
applied to be exposed in the DLL file. If you want to use a different
method name in managed code, you must set the EntryPoint parameter to the
attribute as follows:
[DllImport("Crypt32.dll", EntryPoint="CryptProtectData")]
The following code can be used to wrap the CryptProtectData nd
CryptUnprotectData functions:
[DllImport("crypt32.dll", EntryPoint="CryptProtectData",
CharSet=CharSet.Unicode)]
public static extern bool Encrypt(
ref DataBlob dataIn,
String description,
ref DataBlob optionalEntropy,
IntPtr reserved,
ref CryptProtectPromptStruct promptStruct,
int flags,
out DataBlob dataOut );
[DllImport("crypt32.dll", EntryPoint="CryptUnprotectData",
CharSet=CharSet.Unicode)]
public static extern bool Decrypt(
ref DataBlob dataIn,
String description,
ref DataBlob optionalEntropy,
IntPtr reserved,
ref CryptProtectPromptStruct promptStruct,
int flags,
out DataBlob dataOut );
Download the sample code to test these
DPAPI wrappers.
Back to Tips and Tricks