{"id":452,"date":"2017-01-07T21:24:25","date_gmt":"2017-01-07T13:24:25","guid":{"rendered":"https:\/\/blog.freesilo.com\/?p=452"},"modified":"2017-01-07T21:24:25","modified_gmt":"2017-01-07T13:24:25","slug":"how-to-encrypt-and-decrypt-data-using-dpapi-in-c-or-vb-net","status":"publish","type":"post","link":"https:\/\/freesilo.com\/?p=452","title":{"rendered":"How to encrypt and decrypt data using DPAPI in C# or VB.NET"},"content":{"rendered":"<h2 id=\"Description\" class=\"toc-item\">Description<\/h2>\n<p>These code samples demonstrate how to call Data Protection API (DPAPI) functions <code><a title=\"CryptProtectData function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/Windows\/desktop\/aa380261(v=vs.85).aspx\" target=\"_blank\">CryptProtectData<\/a><\/code> and <code><a title=\"CryptUnprotectData function\" href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/Windows\/desktop\/aa380882(v=vs.85).aspx\" target=\"_blank\">CryptUnprotectData<\/a><\/code> to encrypt and decrypt data in managed code.<\/p>\n<h2 id=\"Background\" class=\"toc-item\">Background<\/h2>\n<p>DPAPI functions encrypt and decrypt data using the <a title=\"Triple-DES\" href=\"http:\/\/en.wikipedia.org\/wiki\/Triple_DES\" target=\"_blank\">Triple-DES<\/a> algorithm. In addition to encryption and decryption, DPAPI handles key generation and protection. DPAPI can generate encryption keys that are unique either for a Windows\u00ae user making the call or the computer on which the program making the call runs. You cannot combine a user-specific key with machine-specific key in a single DPAPI call.<\/p>\n<h3 id=\"UserKey\" class=\"toc-item\">DPAPI with user-specific keys<\/h3>\n<p>When making DPAPI calls with user-specific keys, encryption and decryption must be performed by the same Windows\u00ae user, i.e. the Windows\u00ae account under which the application runs. Applications calling DPAPI functions with user-specific keys must run with loaded user profiles; they cannot use the profiles of the built-in system accounts, such as <code>LocalSystem<\/code>, <code>ASPNET<\/code>, <code>IUSR_MachineName<\/code>, etc. The user profile must be created on the system where DPAPI calls are made, which normally requires the user to log on to the system interactively at least once. IMPORTANT: Normally, ASP.NET applications and other programs running under the built-in system accounts, such as Windows\u00ae services running as <code>LocalSystem<\/code>, cannot use DPAPI with user-specific keys.<\/p>\n<h3 id=\"MachineKey\" class=\"toc-item\">DPAPI with machine-specific keys<\/h3>\n<p>When making DPAPI calls with machine-specific keys, encryption and decryption can be performed by any user or application as long as both operations are executed on the same computer. Any application &#8211; including ASP.NET applications &#8211; can use DPAPI with machine-specific keys. It is worth noting that this option is not secure because it allows a malicious application installed on a system to decrypt any data encrypted by other applications on the same system using DPAPI with machine-specific keys.<\/p>\n<h3 id=\"Entropy\" class=\"toc-item\">Secondary entropy<\/h3>\n<p>When an application calls the DPAPI encryption routine, it can specify an optional secondary entropy (&#8220;secret&#8221; bytes) that will have to be provided by an application attempting to decrypt data. The secondary entropy can be used with either user- or machine-specific keys. It must be protected.<\/p>\n<h3 id=\"Data\" class=\"toc-item\">Data description<\/h3>\n<p>When an application calls the DPAPI encryption routine, it can specify an optional data description. The data description will be returned by the DPAPI decryption routine.<\/p>\n<h2 id=\"Disclaimer\" class=\"toc-item\">Disclaimer<\/h2>\n<p>These code samples are provided for demonstration purpose only. Use at your own risk.<\/p>\n<h2 id=\"License\" class=\"toc-item\">License<\/h2>\n<p>These code samples are released under the <a title=\"Terms of use: Code samples\" href=\"http:\/\/www.obviex.com\/Legal.aspx#Samples\">dual open source license<\/a>.<\/p>\n<h2 id=\"CS\" class=\"toc-item\">C# code sample<\/h2>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\/\/ SAMPLE: Encryption and decryption using DPAPI functions.\r\n\/\/\r\n\/\/ To run this sample, create a new Visual C# project using the Console\r\n\/\/ Application template and replace the contents of the Class1.cs file\r\n\/\/ with the code below.\r\n\/\/\r\n\/\/ THIS CODE AND INFORMATION IS PROVIDED &quot;AS IS&quot; WITHOUT WARRANTY OF ANY\r\n\/\/ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r\n\/\/ IMPLIED WARRANTIES OF MERCHANTABILITY AND\/OR FITNESS FOR A PARTICULAR\r\n\/\/ PURPOSE.\r\n\/\/\r\n\/\/ Copyright (C) 2003 Obviex(TM). All rights reserved.\r\n\/\/\r\nusing System;\r\nusing System.Text;\r\nusing System.Runtime.InteropServices;\r\nusing System.ComponentModel;\r\n\r\n\/\/\/ \r\n&lt;summary&gt;\r\n\/\/\/ Encrypts and decrypts data using DPAPI functions.\r\n\/\/\/ &lt;\/summary&gt;\r\n\r\npublic class DPAPI\r\n{\r\n    \/\/ Wrapper for DPAPI CryptProtectData function.\r\n    &#x5B;DllImport( &quot;crypt32.dll&quot;,\r\n                SetLastError=true,\r\n                CharSet=System.Runtime.InteropServices.CharSet.Auto)]\r\n    private static extern\r\n        bool CryptProtectData(  ref DATA_BLOB     pPlainText,\r\n                                    string        szDescription,\r\n                                ref DATA_BLOB     pEntropy,\r\n                                    IntPtr        pReserved,\r\n                                ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,\r\n                                    int           dwFlags,\r\n                                ref DATA_BLOB     pCipherText);\r\n\r\n    \/\/ Wrapper for DPAPI CryptUnprotectData function.\r\n    &#x5B;DllImport( &quot;crypt32.dll&quot;,\r\n                SetLastError=true,\r\n                CharSet=System.Runtime.InteropServices.CharSet.Auto)]\r\n    private static extern\r\n        bool CryptUnprotectData(ref DATA_BLOB       pCipherText,\r\n                                ref string          pszDescription,\r\n                                ref DATA_BLOB       pEntropy,\r\n                                    IntPtr          pReserved,\r\n                                ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,\r\n                                    int             dwFlags,\r\n                                ref DATA_BLOB       pPlainText);\r\n\r\n    \/\/ BLOB structure used to pass data to DPAPI functions.\r\n    &#x5B;StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]\r\n    internal struct DATA_BLOB\r\n    {\r\n        public int     cbData;\r\n        public IntPtr  pbData;\r\n    }\r\n\r\n    \/\/ Prompt structure to be used for required parameters.\r\n    &#x5B;StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]\r\n    internal struct CRYPTPROTECT_PROMPTSTRUCT\r\n    {\r\n        public int      cbSize;\r\n        public int      dwPromptFlags;\r\n        public IntPtr   hwndApp;\r\n        public string   szPrompt;\r\n    }\r\n\r\n    \/\/ Wrapper for the NULL handle or pointer.\r\n    static private IntPtr NullPtr = ((IntPtr)((int)(0)));\r\n\r\n    \/\/ DPAPI key initialization flags.\r\n    private const int CRYPTPROTECT_UI_FORBIDDEN  = 0x1;\r\n    private const int CRYPTPROTECT_LOCAL_MACHINE = 0x4;\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Initializes empty prompt structure.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;ps&quot;&gt;\r\n    \/\/\/ Prompt parameter (which we do not actually need).\r\n    \/\/\/ &lt;\/param&gt;\r\n    private static void InitPrompt(ref CRYPTPROTECT_PROMPTSTRUCT ps)\r\n    {\r\n        ps.cbSize       = Marshal.SizeOf(\r\n                                  typeof(CRYPTPROTECT_PROMPTSTRUCT));\r\n        ps.dwPromptFlags= 0;\r\n        ps.hwndApp      = NullPtr;\r\n        ps.szPrompt     = null;\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Initializes a BLOB structure from a byte array.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;data&quot;&gt;\r\n    \/\/\/ Original data in a byte array format.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;blob&quot;&gt;\r\n    \/\/\/ Returned blob structure.\r\n    \/\/\/ &lt;\/param&gt;\r\n    private static void InitBLOB(byte&#x5B;] data, ref DATA_BLOB blob)\r\n    {\r\n        \/\/ Use empty array for null parameter.\r\n        if (data == null)\r\n            data = new byte&#x5B;0];\r\n            \r\n        \/\/ Allocate memory for the BLOB data.\r\n        blob.pbData = Marshal.AllocHGlobal(data.Length);\r\n\r\n        \/\/ Make sure that memory allocation was successful.\r\n        if (blob.pbData == IntPtr.Zero)\r\n            throw new Exception(\r\n                &quot;Unable to allocate data buffer for BLOB structure.&quot;);\r\n\r\n        \/\/ Specify number of bytes in the BLOB.\r\n        blob.cbData = data.Length;\r\n\r\n        \/\/ Copy data from original source to the BLOB structure.\r\n        Marshal.Copy(data, 0, blob.pbData, data.Length);\r\n    }\r\n\r\n    \/\/ Flag indicating the type of key. DPAPI terminology refers to\r\n    \/\/ key types as user store or machine store.\r\n    public enum KeyType {UserKey = 1, MachineKey};\r\n\r\n    \/\/ It is reasonable to set default key type to user key.\r\n    private static KeyType defaultKeyType = KeyType.UserKey;\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptProtectData function to encrypt a plaintext\r\n    \/\/\/ string value with a user-specific key. This function does not\r\n    \/\/\/ specify data description and additional entropy.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;plainText&quot;&gt;\r\n    \/\/\/ Plaintext data to be encrypted.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Encrypted value in a base64-encoded format.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    public static string Encrypt(string plainText)\r\n    {\r\n        return Encrypt(defaultKeyType, plainText, String.Empty,\r\n                        String.Empty);\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptProtectData function to encrypt a plaintext\r\n    \/\/\/ string value. This function does not specify data description\r\n    \/\/\/ and additional entropy.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;keyType&quot;&gt;\r\n    \/\/\/ Defines type of encryption key to use. When user key is\r\n    \/\/\/ specified, any application running under the same user account\r\n    \/\/\/ as the one making this call, will be able to decrypt data.\r\n    \/\/\/ Machine key will allow any application running on the same\r\n    \/\/\/ computer where data were encrypted to perform decryption.\r\n    \/\/\/ Note: If optional entropy is specifed, it will be required\r\n    \/\/\/ for decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;plainText&quot;&gt;\r\n    \/\/\/ Plaintext data to be encrypted.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Encrypted value in a base64-encoded format.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    public static string Encrypt(KeyType keyType, string plainText)\r\n    {\r\n        return Encrypt(keyType, plainText, String.Empty,\r\n                        String.Empty);\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptProtectData function to encrypt a plaintext\r\n    \/\/\/ string value. This function does not specify data description.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;keyType&quot;&gt;\r\n    \/\/\/ Defines type of encryption key to use. When user key is\r\n    \/\/\/ specified, any application running under the same user account\r\n    \/\/\/ as the one making this call, will be able to decrypt data.\r\n    \/\/\/ Machine key will allow any application running on the same\r\n    \/\/\/ computer where data were encrypted to perform decryption.\r\n    \/\/\/ Note: If optional entropy is specifed, it will be required\r\n    \/\/\/ for decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;plainText&quot;&gt;\r\n    \/\/\/ Plaintext data to be encrypted.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;entropy&quot;&gt;\r\n    \/\/\/ Optional entropy which - if specified - will be required to\r\n    \/\/\/ perform decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Encrypted value in a base64-encoded format.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    public static string Encrypt(KeyType keyType,\r\n                                 string  plainText,\r\n                                 string  entropy)\r\n    {\r\n        return Encrypt(keyType, plainText, entropy, String.Empty);\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptProtectData function to encrypt a plaintext\r\n    \/\/\/ string value.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;keyType&quot;&gt;\r\n    \/\/\/ Defines type of encryption key to use. When user key is\r\n    \/\/\/ specified, any application running under the same user account\r\n    \/\/\/ as the one making this call, will be able to decrypt data.\r\n    \/\/\/ Machine key will allow any application running on the same\r\n    \/\/\/ computer where data were encrypted to perform decryption.\r\n    \/\/\/ Note: If optional entropy is specifed, it will be required\r\n    \/\/\/ for decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;plainText&quot;&gt;\r\n    \/\/\/ Plaintext data to be encrypted.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;entropy&quot;&gt;\r\n    \/\/\/ Optional entropy which - if specified - will be required to\r\n    \/\/\/ perform decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;description&quot;&gt;\r\n    \/\/\/ Optional description of data to be encrypted. If this value is\r\n    \/\/\/ specified, it will be stored along with encrypted data and\r\n    \/\/\/ returned as a separate value during decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Encrypted value in a base64-encoded format.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    public static string Encrypt(KeyType keyType,\r\n                                 string  plainText,\r\n                                 string  entropy,\r\n                                 string  description)\r\n    {\r\n        \/\/ Make sure that parameters are valid.\r\n        if (plainText == null) plainText = String.Empty;\r\n        if (entropy   == null) entropy   = String.Empty;\r\n\r\n        \/\/ Call encryption routine and convert returned bytes into\r\n        \/\/ a base64-encoded value.\r\n        return Convert.ToBase64String(\r\n                Encrypt(keyType,\r\n                        Encoding.UTF8.GetBytes(plainText),\r\n                        Encoding.UTF8.GetBytes(entropy),\r\n                        description));\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptProtectData function to encrypt an array of\r\n    \/\/\/ plaintext bytes.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;keyType&quot;&gt;\r\n    \/\/\/ Defines type of encryption key to use. When user key is\r\n    \/\/\/ specified, any application running under the same user account\r\n    \/\/\/ as the one making this call, will be able to decrypt data.\r\n    \/\/\/ Machine key will allow any application running on the same\r\n    \/\/\/ computer where data were encrypted to perform decryption.\r\n    \/\/\/ Note: If optional entropy is specifed, it will be required\r\n    \/\/\/ for decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;plainTextBytes&quot;&gt;\r\n    \/\/\/ Plaintext data to be encrypted.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;entropyBytes&quot;&gt;\r\n    \/\/\/ Optional entropy which - if specified - will be required to\r\n    \/\/\/ perform decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;description&quot;&gt;\r\n    \/\/\/ Optional description of data to be encrypted. If this value is\r\n    \/\/\/ specified, it will be stored along with encrypted data and\r\n    \/\/\/ returned as a separate value during decryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Encrypted value.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    public static byte&#x5B;] Encrypt(KeyType keyType,\r\n                                 byte&#x5B;]  plainTextBytes,\r\n                                 byte&#x5B;]  entropyBytes,\r\n                                 string  description)\r\n    {\r\n        \/\/ Make sure that parameters are valid.\r\n        if (plainTextBytes == null) plainTextBytes = new byte&#x5B;0];\r\n        if (entropyBytes   == null) entropyBytes   = new byte&#x5B;0];\r\n        if (description    == null) description    = String.Empty;\r\n\r\n        \/\/ Create BLOBs to hold data.\r\n        DATA_BLOB plainTextBlob  = new DATA_BLOB();\r\n        DATA_BLOB cipherTextBlob = new DATA_BLOB();\r\n        DATA_BLOB entropyBlob    = new DATA_BLOB();\r\n\r\n        \/\/ We only need prompt structure because it is a required\r\n        \/\/ parameter.\r\n        CRYPTPROTECT_PROMPTSTRUCT prompt =\r\n                                  new CRYPTPROTECT_PROMPTSTRUCT();\r\n        InitPrompt(ref prompt);\r\n\r\n        try\r\n        {\r\n            \/\/ Convert plaintext bytes into a BLOB structure.\r\n            try\r\n            {\r\n                InitBLOB(plainTextBytes, ref plainTextBlob);\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                throw new Exception(\r\n                    &quot;Cannot initialize plaintext BLOB.&quot;, ex);\r\n            }\r\n\r\n            \/\/ Convert entropy bytes into a BLOB structure.\r\n            try\r\n            {\r\n                InitBLOB(entropyBytes, ref entropyBlob);\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                throw new Exception(\r\n                    &quot;Cannot initialize entropy BLOB.&quot;, ex);\r\n            }\r\n\r\n            \/\/ Disable any types of UI.\r\n            int flags = CRYPTPROTECT_UI_FORBIDDEN;\r\n\r\n            \/\/ When using machine-specific key, set up machine flag.\r\n            if (keyType == KeyType.MachineKey)\r\n                flags |= CRYPTPROTECT_LOCAL_MACHINE;\r\n\r\n            \/\/ Call DPAPI to encrypt data.\r\n            bool success = CryptProtectData(ref plainTextBlob,\r\n                                                description,\r\n                                            ref entropyBlob,\r\n                                                IntPtr.Zero,\r\n                                            ref prompt,\r\n                                                flags,\r\n                                            ref cipherTextBlob);\r\n            \/\/ Check the result.\r\n            if (!success)\r\n            {\r\n                \/\/ If operation failed, retrieve last Win32 error.\r\n                int errCode = Marshal.GetLastWin32Error();\r\n\r\n                \/\/ Win32Exception will contain error message corresponding\r\n                \/\/ to the Windows error code.\r\n                throw new Exception(\r\n                    &quot;CryptProtectData failed.&quot;, new Win32Exception(errCode));\r\n            }\r\n\r\n            \/\/ Allocate memory to hold ciphertext.\r\n            byte&#x5B;] cipherTextBytes = new byte&#x5B;cipherTextBlob.cbData];\r\n\r\n            \/\/ Copy ciphertext from the BLOB to a byte array.\r\n            Marshal.Copy(cipherTextBlob.pbData,\r\n                            cipherTextBytes,\r\n                            0,\r\n                            cipherTextBlob.cbData);\r\n\r\n            \/\/ Return the result.\r\n            return cipherTextBytes;\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            throw new Exception(&quot;DPAPI was unable to encrypt data.&quot;, ex);\r\n        }\r\n        \/\/ Free all memory allocated for BLOBs.\r\n        finally\r\n        {\r\n            if (plainTextBlob.pbData != IntPtr.Zero)\r\n                Marshal.FreeHGlobal(plainTextBlob.pbData);\r\n\r\n            if (cipherTextBlob.pbData != IntPtr.Zero)\r\n                Marshal.FreeHGlobal(cipherTextBlob.pbData);\r\n\r\n            if (entropyBlob.pbData != IntPtr.Zero)\r\n                Marshal.FreeHGlobal(entropyBlob.pbData);\r\n        }\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    \/\/\/ This function does not use additional entropy and does not\r\n    \/\/\/ return data description.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;cipherText&quot;&gt;\r\n    \/\/\/ Encrypted data formatted as a base64-encoded string.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Decrypted data returned as a UTF-8 string.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    \/\/\/ &lt;remarks&gt;\r\n    \/\/\/ When decrypting data, it is not necessary to specify which\r\n    \/\/\/ type of encryption key to use: user-specific or\r\n    \/\/\/ machine-specific; DPAPI will figure it out by looking at\r\n    \/\/\/ the signature of encrypted data.\r\n    \/\/\/ &lt;\/remarks&gt;\r\n    public static string Decrypt(string cipherText)\r\n    {\r\n        string description;\r\n\r\n        return Decrypt(cipherText, String.Empty, out description);\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    \/\/\/ This function does not use additional entropy.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;cipherText&quot;&gt;\r\n    \/\/\/ Encrypted data formatted as a base64-encoded string.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;description&quot;&gt;\r\n    \/\/\/ Returned description of data specified during encryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Decrypted data returned as a UTF-8 string.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    \/\/\/ &lt;remarks&gt;\r\n    \/\/\/ When decrypting data, it is not necessary to specify which\r\n    \/\/\/ type of encryption key to use: user-specific or\r\n    \/\/\/ machine-specific; DPAPI will figure it out by looking at\r\n    \/\/\/ the signature of encrypted data.\r\n    \/\/\/ &lt;\/remarks&gt;\r\n    public static string Decrypt(    string cipherText,\r\n                                 out string description)\r\n    {\r\n        return Decrypt(cipherText, String.Empty, out description);\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;cipherText&quot;&gt;\r\n    \/\/\/ Encrypted data formatted as a base64-encoded string.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;entropy&quot;&gt;\r\n    \/\/\/ Optional entropy, which is required if it was specified during\r\n    \/\/\/ encryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;description&quot;&gt;\r\n    \/\/\/ Returned description of data specified during encryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Decrypted data returned as a UTF-8 string.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    \/\/\/ &lt;remarks&gt;\r\n    \/\/\/ When decrypting data, it is not necessary to specify which\r\n    \/\/\/ type of encryption key to use: user-specific or\r\n    \/\/\/ machine-specific; DPAPI will figure it out by looking at\r\n    \/\/\/ the signature of encrypted data.\r\n    \/\/\/ &lt;\/remarks&gt;\r\n    public static string Decrypt(    string cipherText,\r\n                                     string entropy,\r\n                                 out string description)\r\n    {\r\n        \/\/ Make sure that parameters are valid.\r\n        if (entropy == null) entropy = String.Empty;\r\n\r\n        return Encoding.UTF8.GetString(\r\n                    Decrypt(    Convert.FromBase64String(cipherText),\r\n                                Encoding.UTF8.GetBytes(entropy),\r\n                            out description));\r\n    }\r\n\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    \/\/\/ &lt;param name=&quot;cipherTextBytes&quot;&gt;\r\n    \/\/\/ Encrypted data.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;entropyBytes&quot;&gt;\r\n    \/\/\/ Optional entropy, which is required if it was specified during\r\n    \/\/\/ encryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;param name=&quot;description&quot;&gt;\r\n    \/\/\/ Returned description of data specified during encryption.\r\n    \/\/\/ &lt;\/param&gt;\r\n    \/\/\/ &lt;returns&gt;\r\n    \/\/\/ Decrypted data bytes.\r\n    \/\/\/ &lt;\/returns&gt;\r\n    \/\/\/ &lt;remarks&gt;\r\n    \/\/\/ When decrypting data, it is not necessary to specify which\r\n    \/\/\/ type of encryption key to use: user-specific or\r\n    \/\/\/ machine-specific; DPAPI will figure it out by looking at\r\n    \/\/\/ the signature of encrypted data.\r\n    \/\/\/ &lt;\/remarks&gt;\r\n    public static byte&#x5B;] Decrypt(    byte&#x5B;] cipherTextBytes,\r\n                                     byte&#x5B;] entropyBytes,\r\n                                 out string description)\r\n    {\r\n        \/\/ Create BLOBs to hold data.\r\n        DATA_BLOB plainTextBlob  = new DATA_BLOB();\r\n        DATA_BLOB cipherTextBlob = new DATA_BLOB();\r\n        DATA_BLOB entropyBlob    = new DATA_BLOB();\r\n\r\n        \/\/ We only need prompt structure because it is a required\r\n        \/\/ parameter.\r\n        CRYPTPROTECT_PROMPTSTRUCT prompt =\r\n                                  new CRYPTPROTECT_PROMPTSTRUCT();\r\n        InitPrompt(ref prompt);\r\n\r\n        \/\/ Initialize description string.\r\n        description = String.Empty;\r\n\r\n        try\r\n        {\r\n            \/\/ Convert ciphertext bytes into a BLOB structure.\r\n            try\r\n            {\r\n                InitBLOB(cipherTextBytes, ref cipherTextBlob);\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                throw new Exception(\r\n                    &quot;Cannot initialize ciphertext BLOB.&quot;, ex);\r\n            }\r\n\r\n            \/\/ Convert entropy bytes into a BLOB structure.\r\n            try\r\n            {\r\n                InitBLOB(entropyBytes, ref entropyBlob);\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                throw new Exception(\r\n                    &quot;Cannot initialize entropy BLOB.&quot;, ex);\r\n            }\r\n\r\n            \/\/ Disable any types of UI. CryptUnprotectData does not\r\n            \/\/ mention CRYPTPROTECT_LOCAL_MACHINE flag in the list of\r\n            \/\/ supported flags so we will not set it up.\r\n            int flags = CRYPTPROTECT_UI_FORBIDDEN;\r\n\r\n            \/\/ Call DPAPI to decrypt data.\r\n            bool success = CryptUnprotectData(ref cipherTextBlob,\r\n                                              ref description,\r\n                                              ref entropyBlob,\r\n                                                  IntPtr.Zero,\r\n                                              ref prompt,\r\n                                                  flags,\r\n                                              ref plainTextBlob);\r\n\r\n            \/\/ Check the result.\r\n            if (!success)\r\n            {\r\n                \/\/ If operation failed, retrieve last Win32 error.\r\n                int errCode = Marshal.GetLastWin32Error();\r\n\r\n                \/\/ Win32Exception will contain error message corresponding\r\n                \/\/ to the Windows error code.\r\n                throw new Exception(\r\n                    &quot;CryptUnprotectData failed.&quot;, new Win32Exception(errCode));\r\n            }\r\n\r\n            \/\/ Allocate memory to hold plaintext.\r\n            byte&#x5B;] plainTextBytes = new byte&#x5B;plainTextBlob.cbData];\r\n\r\n            \/\/ Copy ciphertext from the BLOB to a byte array.\r\n            Marshal.Copy(plainTextBlob.pbData,\r\n                         plainTextBytes,\r\n                         0,\r\n                         plainTextBlob.cbData);\r\n\r\n            \/\/ Return the result.\r\n            return plainTextBytes;\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            throw new Exception(&quot;DPAPI was unable to decrypt data.&quot;, ex);\r\n        }\r\n        \/\/ Free all memory allocated for BLOBs.\r\n        finally\r\n        {\r\n            if (plainTextBlob.pbData != IntPtr.Zero)\r\n                Marshal.FreeHGlobal(plainTextBlob.pbData);\r\n\r\n            if (cipherTextBlob.pbData != IntPtr.Zero)\r\n                Marshal.FreeHGlobal(cipherTextBlob.pbData);\r\n\r\n            if (entropyBlob.pbData != IntPtr.Zero)\r\n                Marshal.FreeHGlobal(entropyBlob.pbData);\r\n        }\r\n    }\r\n}\r\n\r\n\/\/\/ \r\n&lt;summary&gt;\r\n\/\/\/ Demonstrates the use of DPAPI functions to encrypt and decrypt data.\r\n\/\/\/ &lt;\/summary&gt;\r\n\r\npublic class DPAPITest\r\n{\r\n    \/\/\/ \r\n&lt;summary&gt;\r\n    \/\/\/ The main entry point for the application.\r\n    \/\/\/ &lt;\/summary&gt;\r\n\r\n    &#x5B;STAThread]\r\n    static void Main(string&#x5B;] args)\r\n    {\r\n        try\r\n        {\r\n            string text    = &quot;Hello, world!&quot;;\r\n            string entropy = null;\r\n            string description;\r\n\r\n            Console.WriteLine(&quot;Plaintext: {0}\\r\\n&quot;, text);\r\n\r\n            \/\/ Call DPAPI to encrypt data with user-specific key.\r\n            string encrypted = DPAPI.Encrypt( DPAPI.KeyType.UserKey,\r\n                                              text,\r\n                                              entropy,\r\n                                              &quot;My Data&quot;);\r\n            Console.WriteLine(&quot;Encrypted: {0}\\r\\n&quot;, encrypted);\r\n\r\n            \/\/ Call DPAPI to decrypt data.\r\n            string decrypted = DPAPI.Decrypt(   encrypted,\r\n                                                entropy,\r\n                                            out description);\r\n            Console.WriteLine(&quot;Decrypted: {0} &lt;&lt;&lt;{1}&gt;&gt;&gt;\\r\\n&quot;,\r\n                               decrypted, description);\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            while (ex != null)\r\n            {\r\n                Console.WriteLine(ex.Message);\r\n                ex = ex.InnerException;\r\n            }\r\n        }\r\n    }\r\n}\r\n\/\/\r\n\/\/ END OF FILE\r\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\r\n\r\n<\/pre>\n<h2 id=\"VB\" class=\"toc-item\">VB.NET code sample<\/h2>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\r\n' SAMPLE: Encryption and decryption using DPAPI functions.\r\n'\r\n' To run this sample, create a new Visual Basic.NET project using the Console\r\n' Application template and replace the contents of the Module1.vb file with\r\n' the code below.\r\n'\r\n' THIS CODE AND INFORMATION IS PROVIDED &quot;AS IS&quot; WITHOUT WARRANTY OF ANY\r\n' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r\n' IMPLIED WARRANTIES OF MERCHANTABILITY AND\/OR FITNESS FOR A PARTICULAR\r\n' PURPOSE.\r\n'\r\n' Copyright (C) 2003 Obviex(TM). All rights reserved.\r\n'\r\nImports System\r\nImports System.Text\r\nImports System.Runtime.InteropServices\r\nImports System.ComponentModel\r\nImports Microsoft.VisualBasic\r\n\r\nPublic Module Module1\r\n\r\n' &lt;summary&gt;\r\n' Encrypts and decrypts data using DPAPI functions.\r\n' &lt;\/summary&gt;\r\nPublic Class DPAPI\r\n\r\n    ' Wrapper for DPAPI CryptProtectData function.\r\n    &lt;DllImport(&quot;crypt32.dll&quot;, SetLastError:=True, CharSet:=CharSet.Auto)&gt; _\r\n    Private Shared Function CryptProtectData _\r\n    ( _\r\n        ByRef pPlainText    As DATA_BLOB, _\r\n        ByVal szDescription As String, _\r\n        ByRef pEntropy      As DATA_BLOB, _\r\n        ByVal pReserved     As IntPtr, _\r\n        ByRef pPrompt       As CRYPTPROTECT_PROMPTSTRUCT, _\r\n        ByVal dwFlags       As Integer, _\r\n        ByRef pCipherText   As DATA_BLOB _\r\n    ) As Boolean\r\n    End Function\r\n\r\n    ' Wrapper for DPAPI CryptUnprotectData function.\r\n    &lt;DllImport(&quot;crypt32.dll&quot;, SetLastError:=True, CharSet:=CharSet.Auto)&gt; _\r\n    Private Shared Function CryptUnprotectData _\r\n    ( _\r\n        ByRef pCipherText    As DATA_BLOB, _\r\n        ByRef pszDescription As String, _\r\n        ByRef pEntropy       As DATA_BLOB, _\r\n        ByVal pReserved      As IntPtr, _\r\n        ByRef pPrompt        As CRYPTPROTECT_PROMPTSTRUCT, _\r\n        ByVal dwFlags        As Integer, _\r\n        ByRef pPlainText     As DATA_BLOB _\r\n    ) As Boolean\r\n    End Function\r\n\r\n    ' BLOB structure used to pass data to DPAPI functions.\r\n    &lt;StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)&gt; _\r\n    Friend Structure DATA_BLOB\r\n        Public cbData As Integer\r\n        Public pbData As IntPtr\r\n    End Structure\r\n\r\n    ' Prompt structure to be used for required parameters.\r\n    &lt;StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)&gt; _\r\n    Friend Structure CRYPTPROTECT_PROMPTSTRUCT\r\n        Public cbSize        As Integer\r\n        Public dwPromptFlags As Integer\r\n        Public hwndApp       As IntPtr\r\n        Public szPrompt      As String\r\n    End Structure\r\n\r\n    ' DPAPI key initialization flags.\r\n    Private Const CRYPTPROTECT_UI_FORBIDDEN  As Integer = 1\r\n    Private Const CRYPTPROTECT_LOCAL_MACHINE As Integer = 4\r\n\r\n    ' &lt;summary&gt;\r\n    ' Initializes empty prompt structure.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;ps&quot;&gt;\r\n    ' Prompt parameter (which we do not actually need).\r\n    ' &lt;\/param&gt;\r\n    Private Shared Sub InitPrompt _\r\n    ( _\r\n        ByRef ps As CRYPTPROTECT_PROMPTSTRUCT _\r\n    )\r\n        ps.cbSize        = Marshal.SizeOf(GetType(CRYPTPROTECT_PROMPTSTRUCT))\r\n        ps.dwPromptFlags = 0\r\n        ps.hwndApp       = IntPtr.Zero\r\n        ps.szPrompt      = Nothing\r\n    End Sub\r\n\r\n    ' &lt;summary&gt;\r\n    ' Initializes a BLOB structure from a byte array.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;data&quot;&gt;\r\n    ' Original data in a byte array format.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;blob&quot;&gt;\r\n    ' Returned blob structure.\r\n    ' &lt;\/param&gt;\r\n    Private Shared Sub InitBLOB _\r\n    ( _\r\n        ByVal data As Byte(), _\r\n        ByRef blob As DATA_BLOB _\r\n    )\r\n        ' Use empty array for null parameter.\r\n        If data Is Nothing Then\r\n            data = New Byte(0){}\r\n        End If\r\n            \r\n        ' Allocate memory for the BLOB data.\r\n        blob.pbData = Marshal.AllocHGlobal(data.Length)\r\n\r\n        ' Make sure that memory allocation was successful.\r\n        If blob.pbData.Equals(IntPtr.Zero) Then\r\n            Throw New Exception( _\r\n                    &quot;Unable to allocate data buffer for BLOB structure.&quot;)\r\n        End If\r\n\r\n        ' Specify number of bytes in the BLOB.\r\n        blob.cbData = data.Length\r\n        Marshal.Copy(data, 0, blob.pbData, data.Length)\r\n    End Sub\r\n\r\n    ' Flag indicating the type of key. DPAPI terminology refers to\r\n    ' key types as user store or machine store.\r\n    Public Enum KeyType\r\n        UserKey = 1\r\n        MachineKey\r\n    End Enum\r\n\r\n    ' It is reasonable to set default key type to user key.\r\n    Private Shared defaultKeyType As KeyType = KeyType.UserKey\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptProtectData function to encrypt a plaintext\r\n    ' string value with a user-specific key. This function does not\r\n    ' specify data description and additional entropy.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;plainText&quot;&gt;\r\n    ' Plaintext data to be encrypted.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Encrypted value in a base64-encoded format.\r\n    ' &lt;\/returns&gt;\r\n    Public Shared Function Encrypt _\r\n    ( _\r\n        ByVal plainText As String _\r\n    ) As String\r\n        Return Encrypt(defaultKeyType, plainText, String.Empty, String.Empty)\r\n    End Function\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptProtectData function to encrypt a plaintext\r\n    ' string value. This function does not specify data description\r\n    ' and additional entropy.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;keyType&quot;&gt;\r\n    ' Defines type of encryption key to use. When user key is\r\n    ' specified, any application running under the same user account\r\n    ' as the one making this call, will be able to decrypt data.\r\n    ' Machine key will allow any application running on the same\r\n    ' computer where data were encrypted to perform decryption.\r\n    ' Note: If optional entropy is specifed, it will be required\r\n    ' for decryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;plainText&quot;&gt;\r\n    ' Plaintext data to be encrypted.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Encrypted value in a base64-encoded format.\r\n    ' &lt;\/returns&gt;\r\n    Public Shared Function Encrypt _\r\n    ( _\r\n        ByVal keyType   As KeyType, _\r\n        ByVal plainText As String _\r\n    ) As String\r\n        Return Encrypt(keyType, plainText, String.Empty, String.Empty)\r\n    End Function\r\n\r\n    Public Shared Function Encrypt _\r\n    ( _\r\n        ByVal keyType   As KeyType, _\r\n        ByVal plainText As String, _\r\n        ByVal entropy   As String _\r\n    ) As String\r\n        Return Encrypt(keyType, plainText, entropy, String.Empty)\r\n    End Function\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptProtectData function to encrypt a plaintext\r\n    ' string value. This function does not specify data description.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;keyType&quot;&gt;\r\n    ' Defines type of encryption key to use. When user key is\r\n    ' specified, any application running under the same user account\r\n    ' as the one making this call, will be able to decrypt data.\r\n    ' Machine key will allow any application running on the same\r\n    ' computer where data were encrypted to perform decryption.\r\n    ' Note: If optional entropy is specifed, it will be required\r\n    ' for decryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;plainText&quot;&gt;\r\n    ' Plaintext data to be encrypted.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;entropy&quot;&gt;\r\n    ' Optional entropy which - if specified - will be required to\r\n    ' perform decryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Encrypted value in a base64-encoded format.\r\n    ' &lt;\/returns&gt;\r\n    Public Shared Function Encrypt _\r\n    ( _\r\n        ByVal keyType     As KeyType, _\r\n        ByVal plainText   As String, _\r\n        ByVal entropy     As String, _\r\n        ByVal description As String _\r\n    ) As String\r\n        If plainText Is Nothing Then\r\n            plainText = String.Empty\r\n        End If\r\n        If entropy Is Nothing Then\r\n            entropy = String.Empty\r\n        End If\r\n        Return Convert.ToBase64String( _\r\n            Encrypt(keyType, _\r\n                    Encoding.UTF8.GetBytes(plainText), _\r\n                    Encoding.UTF8.GetBytes(entropy), _\r\n                    description))\r\n    End Function\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptProtectData function to encrypt an array of\r\n    ' plaintext bytes.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;keyType&quot;&gt;\r\n    ' Defines type of encryption key to use. When user key is\r\n    ' specified, any application running under the same user account\r\n    ' as the one making this call, will be able to decrypt data.\r\n    ' Machine key will allow any application running on the same\r\n    ' computer where data were encrypted to perform decryption.\r\n    ' Note: If optional entropy is specifed, it will be required\r\n    ' for decryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;plainTextBytes&quot;&gt;\r\n    ' Plaintext data to be encrypted.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;entropyBytes&quot;&gt;\r\n    ' Optional entropy which - if specified - will be required to\r\n    ' perform decryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;description&quot;&gt;\r\n    ' Optional description of data to be encrypted. If this value is\r\n    ' specified, it will be stored along with encrypted data and\r\n    ' returned as a separate value during decryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Encrypted value.\r\n    ' &lt;\/returns&gt;\r\n    Public Shared Function Encrypt _\r\n    ( _\r\n        ByVal keyType        As KeyType, _\r\n        ByVal plainTextBytes As Byte(), _\r\n        ByVal entropyBytes   As Byte(), _\r\n        ByVal description    As String _\r\n    ) As Byte()\r\n        ' Make sure that parameters are valid.\r\n        If plainTextBytes Is Nothing Then\r\n            plainTextBytes = New Byte(0){}\r\n        End If\r\n\r\n        If entropyBytes Is Nothing Then\r\n            entropyBytes = New Byte(0){}\r\n        End If\r\n\r\n        If description Is Nothing Then\r\n            description = String.Empty\r\n        End If\r\n\r\n        ' Create BLOBs to hold data.\r\n        Dim plainTextBlob As DATA_BLOB = New DATA_BLOB\r\n        Dim cipherTextBlob As DATA_BLOB = New DATA_BLOB\r\n        Dim entropyBlob As DATA_BLOB = New DATA_BLOB\r\n\r\n        ' We only need prompt structure because it is a required\r\n        ' parameter.\r\n        Dim prompt As _\r\n                CRYPTPROTECT_PROMPTSTRUCT = New CRYPTPROTECT_PROMPTSTRUCT\r\n        InitPrompt(prompt)\r\n\r\n        Try\r\n            ' Convert plaintext bytes into a BLOB structure.\r\n            Try\r\n                InitBLOB(plainTextBytes, plainTextBlob)\r\n            Catch ex As Exception\r\n                Throw New Exception(&quot;Cannot initialize plaintext BLOB.&quot;, ex)\r\n            End Try\r\n\r\n            ' Convert entropy bytes into a BLOB structure.\r\n            Try\r\n                InitBLOB(entropyBytes, entropyBlob)\r\n            Catch ex As Exception\r\n                Throw New Exception(&quot;Cannot initialize entropy BLOB.&quot;, ex)\r\n            End Try\r\n\r\n            ' Disable any types of UI.\r\n            Dim flags As Integer = CRYPTPROTECT_UI_FORBIDDEN\r\n\r\n            ' When using machine-specific key, set up machine flag.\r\n            If keyType = KeyType.MachineKey Then\r\n                flags = flags Or (CRYPTPROTECT_LOCAL_MACHINE)\r\n            End If\r\n\r\n            ' Call DPAPI to encrypt data.\r\n            Dim success As Boolean = CryptProtectData( _\r\n                                            plainTextBlob, _\r\n                                            description, _\r\n                                            entropyBlob, _\r\n                                            IntPtr.Zero, _\r\n                                            prompt, _\r\n                                            flags, _\r\n                                            cipherTextBlob)\r\n\r\n            ' Check the result.\r\n            If Not success Then\r\n                ' If operation failed, retrieve last Win32 error.\r\n                Dim errCode As Integer = Marshal.GetLastWin32Error()\r\n     \r\n                ' Win32Exception will contain error message corresponding\r\n                ' to the Windows error code.\r\n                Throw New Exception(&quot;CryptProtectData failed.&quot;, _\r\n                                New Win32Exception(errCode))\r\n            End If\r\n\r\n            ' Allocate memory to hold ciphertext.\r\n            Dim cipherTextBytes(cipherTextBlob.cbData-1) As Byte\r\n\r\n            ' Copy ciphertext from the BLOB to a byte array.\r\n            Marshal.Copy(cipherTextBlob.pbData, cipherTextBytes, 0, _\r\n                            cipherTextBlob.cbData)\r\n\r\n            ' Return the result.\r\n            Return cipherTextBytes\r\n        Catch ex As Exception\r\n            Throw New Exception(&quot;DPAPI was unable to encrypt data.&quot;, ex)\r\n        Finally\r\n            If Not(plainTextBlob.pbData.Equals(IntPtr.Zero)) Then\r\n                Marshal.FreeHGlobal(plainTextBlob.pbData)\r\n            End If\r\n\r\n            If Not (cipherTextBlob.pbData.Equals(IntPtr.Zero)) Then\r\n                Marshal.FreeHGlobal(cipherTextBlob.pbData)\r\n            End If\r\n\r\n            If Not(entropyBlob.pbData.Equals(IntPtr.Zero)) Then\r\n                Marshal.FreeHGlobal(entropyBlob.pbData)\r\n            End If\r\n        End Try\r\n    End Function\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    ' This function does not use additional entropy and does not\r\n    ' return data description.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;cipherText&quot;&gt;\r\n    ' Encrypted data formatted as a base64-encoded string.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Decrypted data returned as a UTF-8 string.\r\n    ' &lt;\/returns&gt;\r\n    ' &lt;remarks&gt;\r\n    ' When decrypting data, it is not necessary to specify which\r\n    ' type of encryption key to use: user-specific or\r\n    ' machine-specific; DPAPI will figure it out by looking at\r\n    ' the signature of encrypted data.\r\n    ' &lt;\/remarks&gt;\r\n    Public Shared Function Decrypt _\r\n    ( _\r\n        ByVal cipherText As String _\r\n    ) As String\r\n        Dim description As String\r\n        Return Decrypt(cipherText, String.Empty, description)\r\n    End Function\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    ' This function does not use additional entropy.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;cipherText&quot;&gt;\r\n    ' Encrypted data formatted as a base64-encoded string.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;description&quot;&gt;\r\n    ' Returned description of data specified during encryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Decrypted data returned as a UTF-8 string.\r\n    ' &lt;\/returns&gt;\r\n    ' &lt;remarks&gt;\r\n    ' When decrypting data, it is not necessary to specify which\r\n    ' type of encryption key to use: user-specific or\r\n    ' machine-specific; DPAPI will figure it out by looking at\r\n    ' the signature of encrypted data.\r\n    ' &lt;\/remarks&gt;\r\n    Public Shared Function Decrypt _\r\n    ( _\r\n        ByVal cipherText  As String, _\r\n        ByRef description As String _\r\n    ) As String\r\n        Return Decrypt(cipherText, String.Empty, description)\r\n    End Function\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;cipherText&quot;&gt;\r\n    ' Encrypted data formatted as a base64-encoded string.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;entropy&quot;&gt;\r\n    ' Optional entropy, which is required if it was specified during\r\n    ' encryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;description&quot;&gt;\r\n    ' Returned description of data specified during encryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Decrypted data returned as a UTF-8 string.\r\n    ' &lt;\/returns&gt;\r\n    ' &lt;remarks&gt;\r\n    ' When decrypting data, it is not necessary to specify which\r\n    ' type of encryption key to use: user-specific or\r\n    ' machine-specific; DPAPI will figure it out by looking at\r\n    ' the signature of encrypted data.\r\n    ' &lt;\/remarks&gt;\r\n    Public Shared Function Decrypt _\r\n    ( _\r\n        ByVal cipherText  As String, _\r\n        ByVal entropy     As String, _\r\n        ByRef description As String _\r\n    ) As String\r\n        ' Make sure that parameters are valid.\r\n        If entropy Is Nothing Then\r\n            entropy = String.Empty\r\n        End If\r\n\r\n        Return Encoding.UTF8.GetString( _\r\n            Decrypt(Convert.FromBase64String(cipherText), _\r\n                    Encoding.UTF8.GetBytes(entropy), description))\r\n    End Function\r\n\r\n    ' &lt;summary&gt;\r\n    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.\r\n    ' &lt;\/summary&gt;\r\n    ' &lt;param name=&quot;cipherTextBytes&quot;&gt;\r\n    ' Encrypted data.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;entropyBytes&quot;&gt;\r\n    ' Optional entropy, which is required if it was specified during\r\n    ' encryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;param name=&quot;description&quot;&gt;\r\n    ' Returned description of data specified during encryption.\r\n    ' &lt;\/param&gt;\r\n    ' &lt;returns&gt;\r\n    ' Decrypted data bytes.\r\n    ' &lt;\/returns&gt;\r\n    ' &lt;remarks&gt;\r\n    ' When decrypting data, it is not necessary to specify which\r\n    ' type of encryption key to use: user-specific or\r\n    ' machine-specific; DPAPI will figure it out by looking at\r\n    ' the signature of encrypted data.\r\n    ' &lt;\/remarks&gt;\r\n    Public Shared Function Decrypt _\r\n    ( _\r\n        ByVal cipherTextBytes As Byte(), _\r\n        ByVal entropyBytes As Byte(), _\r\n        ByRef description As String _\r\n    ) As Byte()\r\n\r\n        ' Create BLOBs to hold data.\r\n        Dim plainTextBlob  As DATA_BLOB = New DATA_BLOB\r\n        Dim cipherTextBlob As DATA_BLOB = New DATA_BLOB\r\n        Dim entropyBlob    As DATA_BLOB = New DATA_BLOB\r\n\r\n        ' We only need prompt structure because it is a required\r\n        ' parameter.\r\n        Dim prompt As _\r\n                CRYPTPROTECT_PROMPTSTRUCT = New CRYPTPROTECT_PROMPTSTRUCT\r\n        InitPrompt(prompt)\r\n       \r\n        ' Initialize description string.\r\n        description = String.Empty\r\n\r\n        Try\r\n            ' Convert ciphertext bytes into a BLOB structure.\r\n            Try\r\n                InitBLOB(cipherTextBytes, cipherTextBlob)\r\n            Catch ex As Exception\r\n                Throw New Exception(&quot;Cannot initialize ciphertext BLOB.&quot;, ex)\r\n            End Try\r\n\r\n            ' Convert entropy bytes into a BLOB structure.\r\n            Try\r\n                InitBLOB(entropyBytes, entropyBlob)\r\n            Catch ex As Exception\r\n                Throw New Exception(&quot;Cannot initialize entropy BLOB.&quot;, ex)\r\n            End Try\r\n\r\n            ' Disable any types of UI. CryptUnprotectData does not\r\n            ' mention CRYPTPROTECT_LOCAL_MACHINE flag in the list of\r\n            ' supported flags so we will not set it up.\r\n            Dim flags As Integer = CRYPTPROTECT_UI_FORBIDDEN\r\n           \r\n            ' Call DPAPI to decrypt data.\r\n            Dim success As Boolean = CryptUnprotectData( _\r\n                                            cipherTextBlob, _\r\n                                            description, _\r\n                                            entropyBlob, _\r\n                                            IntPtr.Zero, _\r\n                                            prompt, _\r\n                                            flags, _\r\n                                            plainTextBlob)\r\n\r\n            ' Check the result.\r\n            If Not success Then\r\n                ' If operation failed, retrieve last Win32 error.\r\n                Dim errCode As Integer = Marshal.GetLastWin32Error()\r\n\r\n                ' Win32Exception will contain error message corresponding\r\n                ' to the Windows error code.\r\n                Throw New Exception(&quot;CryptUnprotectData failed.&quot;, _\r\n                            New Win32Exception(errCode))\r\n            End If\r\n\r\n            ' Allocate memory to hold plaintext.\r\n            Dim plainTextBytes(plainTextBlob.cbData-1) As Byte\r\n\r\n            ' Copy ciphertext from the BLOB to a byte array.\r\n            Marshal.Copy(plainTextBlob.pbData, plainTextBytes, 0, _\r\n                            plainTextBlob.cbData)\r\n\r\n            ' Return the result.\r\n            Return plainTextBytes\r\n        Catch ex As Exception\r\n            Throw New Exception(&quot;DPAPI was unable to decrypt data.&quot;, ex)\r\n        ' Free all memory allocated for BLOBs.\r\n        Finally\r\n            If Not(plainTextBlob.pbData.Equals(IntPtr.Zero)) Then\r\n                Marshal.FreeHGlobal(plainTextBlob.pbData)\r\n            End If\r\n\r\n            If Not(cipherTextBlob.pbData.Equals(IntPtr.Zero)) Then\r\n                Marshal.FreeHGlobal(cipherTextBlob.pbData)\r\n            End If\r\n\r\n            If Not(entropyBlob.pbData.Equals(IntPtr.Zero)) Then\r\n                Marshal.FreeHGlobal(entropyBlob.pbData)\r\n            End If\r\n        End Try\r\n    End Function\r\nEnd Class\r\n\r\n' &lt;summary&gt;\r\n' The main entry point for the application.\r\n' &lt;\/summary&gt;\r\nSub Main(ByVal args As String())\r\n    Try\r\n        Dim text        As String = &quot;Hello, world!&quot;\r\n        Dim entropy     As String = Nothing\r\n        Dim description As String\r\n        Dim encrypted   As String\r\n        Dim decrypted   As String\r\n\r\n        Console.WriteLine(&quot;Plaintext: {0}&quot; &amp; Chr(13) &amp; Chr(10), text)\r\n\r\n        ' Call DPAPI to encrypt data with user-specific key.\r\n        encrypted  = DPAPI.Encrypt( DPAPI.KeyType.UserKey, _\r\n                                    text, entropy, &quot;My Data&quot;)\r\n\r\n        Console.WriteLine(&quot;Encrypted: {0}&quot; &amp; Chr(13) &amp; Chr(10), encrypted)\r\n\r\n        ' Call DPAPI to decrypt data.\r\n        decrypted = DPAPI.Decrypt(encrypted, entropy, description)\r\n\r\n        Console.WriteLine(&quot;Decrypted: {0} &lt;&lt;&lt;{1}&gt;&gt;&gt;&quot; &amp; Chr(13) &amp; Chr(10), _\r\n                            decrypted, description)\r\n    Catch ex As Exception\r\n        While Not (ex Is Nothing)\r\n            Console.WriteLine(ex.Message)\r\n            ex = ex.InnerException\r\n        End While\r\n    End Try\r\nEnd Sub\r\n\r\nEnd Module\r\n'\r\n' END OF FILE\r\n'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''\r\n<\/pre>\n<h2 id=\"Output\" class=\"toc-item\">Program output<\/h2>\n<pre><code class=\"undefined\">Plaintext: Hello, world!\r\n\r\nEncrypted: AQAAANCMnd8BFdERjHoAwE\/Cl+sBAAAA\/n...AAAAD3e2CVOMOk3awsn7mR7NdMubogt\r\n\r\nDecrypted: Hello, world! &lt;&lt;&lt;My Data&gt;&gt;&gt;\r\n\r\n<\/code><\/pre>\n<p>\u539f\u6587\uff1a<br \/>\nhttp:\/\/www.obviex.com\/samples\/Dpapi.aspx#<br \/>\n\u53c2\u8003\uff1a<br \/>\nhttps:\/\/msdn.microsoft.com\/en-us\/library\/ms995355.aspx<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Description These code samples demonstra&#8230;<br \/><a class=\"read-more-button\" href=\"https:\/\/freesilo.com\/?p=452\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-452","post","type-post","status-publish","format-standard","hentry","category-csharp"],"_links":{"self":[{"href":"https:\/\/freesilo.com\/index.php?rest_route=\/wp\/v2\/posts\/452","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/freesilo.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/freesilo.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/freesilo.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/freesilo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=452"}],"version-history":[{"count":3,"href":"https:\/\/freesilo.com\/index.php?rest_route=\/wp\/v2\/posts\/452\/revisions"}],"predecessor-version":[{"id":455,"href":"https:\/\/freesilo.com\/index.php?rest_route=\/wp\/v2\/posts\/452\/revisions\/455"}],"wp:attachment":[{"href":"https:\/\/freesilo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=452"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/freesilo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=452"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/freesilo.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=452"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}