unsafe public static byte[] CryptProtectString(
            string str, string description, uint dwFlags, string promptText)
        {
            // output buffer
            DATA_BLOB dataOut = new DATA_BLOB();

            try
            {
                // prompt struct
                CRYPTPROTECT_PROMPTSTRUCT promptStruct = new CRYPTPROTECT_PROMPTSTRUCT();
                promptStruct.cbSize = (uint)Marshal.SizeOf(promptStruct);
                if (promptText != null)
                {
                    promptStruct.dwPromptFlags = CRYPTPROTECT.PROMPT_ON_PROTECT;
                    promptStruct.szPrompt = promptText;
                }

                // pin buffer for encrypt
                fixed (char* data = str)
                {
                    // input buffer
                    DATA_BLOB dataIn = new DATA_BLOB();
                    dataIn.cbData = (uint)((str.Length + 1) * 2);
                    dataIn.pbData = new IntPtr(data);

                    // attempt to encrypt the data
                    if (!CryptProtectData(
                        ref dataIn,         // data-input
                        description,    // description of data
                        IntPtr.Zero,        // no entropy data
                        IntPtr.Zero,        // reserved
                        ref promptStruct,   // prompt-info
                        dwFlags,            // flags
                        ref dataOut))
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(), "Error encryting " + description);
                    }
                }

                // return the encrtyped data as a managed byte-array
                byte[] encryptedData = new byte[dataOut.cbData];
                Marshal.Copy(dataOut.pbData, encryptedData, 0, (int)dataOut.cbData);
                return encryptedData;
            }
            finally
            {
                if (dataOut.pbData != IntPtr.Zero)
                    Kernel32.LocalFree(dataOut.pbData);
            }
        }
        unsafe public static string CryptUnprotectString(
            byte[] encryptedStr, out string description, uint flags, string promptText)
        {
            // out variables
            IntPtr dataDescription = IntPtr.Zero;
            DATA_BLOB dataOut = new DATA_BLOB();

            try
            {
                // prompt struct
                CRYPTPROTECT_PROMPTSTRUCT promptStruct = new CRYPTPROTECT_PROMPTSTRUCT();
                promptStruct.cbSize = (uint)Marshal.SizeOf(promptStruct);
                if (promptText != null)
                {
                    promptStruct.dwPromptFlags = CRYPTPROTECT.PROMPT_ON_UNPROTECT;
                    promptStruct.szPrompt = promptText;
                }

                // pin buffer for decryption
                fixed (byte* data = encryptedStr)
                {
                    // encrypted data
                    DATA_BLOB encrtypedData = new DATA_BLOB();
                    encrtypedData.cbData = (uint)encryptedStr.Length;
                    encrtypedData.pbData = new IntPtr(data);

                    // unencrypt
                    if (!CryptUnprotectData(
                        ref encrtypedData,
                        out dataDescription,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        ref promptStruct,
                        flags,
                        ref dataOut))
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error(), "Error decrypting data");
                    }

                    // return the string
                    description = Marshal.PtrToStringUni(dataDescription);
                    return Marshal.PtrToStringUni(dataOut.pbData);
                }
            }
            finally
            {
                if (dataDescription != IntPtr.Zero)
                    Kernel32.LocalFree(dataDescription);

                if (dataOut.pbData != IntPtr.Zero)
                    Kernel32.LocalFree(dataOut.pbData);
            }
        }
 public static extern bool CryptUnprotectData(
     ref DATA_BLOB pDataIn,
     out IntPtr ppszDataDescr,
     IntPtr pOptionalEntropy,
     IntPtr pvReserved,
     ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct,
     uint dwFlags,
     ref DATA_BLOB pDataOut
     );
 public static extern bool CryptProtectData(
     ref DATA_BLOB pDataIn,
     [MarshalAs(UnmanagedType.LPWStr)] string szDataDescr,
     IntPtr pOptionalEntropy,
     IntPtr pvReserved,
     ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct,
     uint dwFlags,
     ref DATA_BLOB pDataOut
     );