zoukankan      html  css  js  c++  java
  • How To: Use DPAPI to Encrypt and Decrypt Data

    The code below demonstrates how to call Data Protection API (DPAPI) functions
    CryptProtectData and CryptUnprotectData to encrypt and decrypt data. The code
    sample is provided in C#.

    Introduction DPAPI functions encrypt and decrypt data using the Triple-DES algorithm. In addition to encryption and decryption, the API handles key generation and protection. DPAPI can generate two types of encryption keys: user- or machine-specific (these key types are commonly referred to as user store and machine store). User store and machine store are mutually exclusive; this means that you cannot combine a user-specific key with machine-specific key in one DPAPI call.

    DPAPI with user store When making DPAPI calls with user-specific keys, encryption and decryption must be performed by the same user (i.e. the identity under which the application runs). Applications calling DPAPI functions with user-specific keys must run with loaded user profiles of Windows® domain or local accounts; they cannot use the profiles of the built-in system accounts, such as LocalSystem, ASPNET, IUSR_MachineName, 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: ASP.NET applications and other programs running under the built-in system accounts, such as Windows® services running as LocalSystem, cannot use DPAPI with user-specific keys.

    DPAPI with machine store 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 - including ASP.NET - 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.

    Secondary entropy When an application calls the DPAPI encryption function, it can specify an optional secondary entropy ("secret" bytes) which 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.

    Data description When an application calls the DPAPI encryption function, it can specify an optional data description, which will be returned by the DPAPI decryption routine.

    More info For additional information about using DPAPI in .NET, check Building Secure ASP.NET Applications, which provides a brief description of DPAPI and several code samples. For a detailed overview of DPAPI, read the Windows Data Protection article.

    Resources Our FREE CipherLite.NET™ tool provides a GUI and library, which you can use to encrypt and decrypt data with DPAPI.

    View Code
      1 ///////////////////////////////////////////////////////////////////////////////
      2 // SAMPLE: Encryption and decryption using DPAPI functions.
      3 //
      4 // To run this sample, create a new Visual C# project using the Console
      5 // Application template and replace the contents of the Class1.cs file
      6 // with the code below.
      7 //
      8 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
      9 // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
     10 // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
     11 // PURPOSE.
     12 //
     13 // Copyright (C) 2003 Obviex(TM). All rights reserved.
     14 //
     15 using System;
     16 using System.Text;
     17 using System.Runtime.InteropServices;
     18 using System.ComponentModel;
     19 
     20 /// <summary>
     21 /// Encrypts and decrypts data using DPAPI functions.
     22 /// </summary>
     23 public class DPAPI
     24 {
     25     // Wrapper for DPAPI CryptProtectData function.
     26     [DllImport( "crypt32.dll",
     27                 SetLastError=true,
     28                 CharSet=System.Runtime.InteropServices.CharSet.Auto)]
     29     private static extern
     30         bool CryptProtectData(  ref DATA_BLOB     pPlainText,
     31                                     string        szDescription,
     32                                 ref DATA_BLOB     pEntropy,
     33                                     IntPtr        pReserved,
     34                                 ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,
     35                                     int           dwFlags,
     36                                 ref DATA_BLOB     pCipherText);
     37 
     38     // Wrapper for DPAPI CryptUnprotectData function.
     39     [DllImport( "crypt32.dll",
     40                 SetLastError=true,
     41                 CharSet=System.Runtime.InteropServices.CharSet.Auto)]
     42     private static extern
     43         bool CryptUnprotectData(ref DATA_BLOB       pCipherText,
     44                                 ref string          pszDescription,
     45                                 ref DATA_BLOB       pEntropy,
     46                                     IntPtr          pReserved,
     47                                 ref CRYPTPROTECT_PROMPTSTRUCT pPrompt,
     48                                     int             dwFlags,
     49                                 ref DATA_BLOB       pPlainText);
     50 
     51     // BLOB structure used to pass data to DPAPI functions.
     52     [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
     53     internal struct DATA_BLOB
     54     {
     55         public int     cbData;
     56         public IntPtr  pbData;
     57     }
     58 
     59     // Prompt structure to be used for required parameters.
     60     [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
     61     internal struct CRYPTPROTECT_PROMPTSTRUCT
     62     {
     63         public int      cbSize;
     64         public int      dwPromptFlags;
     65         public IntPtr   hwndApp;
     66         public string   szPrompt;
     67     }
     68 
     69     // Wrapper for the NULL handle or pointer.
     70     static private IntPtr NullPtr = ((IntPtr)((int)(0)));
     71 
     72     // DPAPI key initialization flags.
     73     private const int CRYPTPROTECT_UI_FORBIDDEN  = 0x1;
     74     private const int CRYPTPROTECT_LOCAL_MACHINE = 0x4;
     75 
     76     /// <summary>
     77     /// Initializes empty prompt structure.
     78     /// </summary>
     79     /// <param name="ps">
     80     /// Prompt parameter (which we do not actually need).
     81     /// </param>
     82     private static void InitPrompt(ref CRYPTPROTECT_PROMPTSTRUCT ps)
     83     {
     84         ps.cbSize       = Marshal.SizeOf(
     85                                   typeof(CRYPTPROTECT_PROMPTSTRUCT));
     86         ps.dwPromptFlags= 0;
     87         ps.hwndApp      = NullPtr;
     88         ps.szPrompt     = null;
     89     }
     90 
     91     /// <summary>
     92     /// Initializes a BLOB structure from a byte array.
     93     /// </summary>
     94     /// <param name="data">
     95     /// Original data in a byte array format.
     96     /// </param>
     97     /// <param name="blob">
     98     /// Returned blob structure.
     99     /// </param>
    100     private static void InitBLOB(byte[] data, ref DATA_BLOB blob)
    101     {
    102         // Use empty array for null parameter.
    103         if (data == null)
    104             data = new byte[0];
    105             
    106         // Allocate memory for the BLOB data.
    107         blob.pbData = Marshal.AllocHGlobal(data.Length);
    108 
    109         // Make sure that memory allocation was successful.
    110         if (blob.pbData == IntPtr.Zero)
    111             throw new Exception(
    112                 "Unable to allocate data buffer for BLOB structure.");
    113 
    114         // Specify number of bytes in the BLOB.
    115         blob.cbData = data.Length;
    116 
    117         // Copy data from original source to the BLOB structure.
    118         Marshal.Copy(data, 0, blob.pbData, data.Length);
    119     }
    120 
    121     // Flag indicating the type of key. DPAPI terminology refers to
    122     // key types as user store or machine store.
    123     public enum KeyType {UserKey = 1, MachineKey};
    124 
    125     // It is reasonable to set default key type to user key.
    126     private static KeyType defaultKeyType = KeyType.UserKey;
    127 
    128     /// <summary>
    129     /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    130     /// string value with a user-specific key. This function does not
    131     /// specify data description and additional entropy.
    132     /// </summary>
    133     /// <param name="plainText">
    134     /// Plaintext data to be encrypted.
    135     /// </param>
    136     /// <returns>
    137     /// Encrypted value in a base64-encoded format.
    138     /// </returns>
    139     public static string Encrypt(string plainText)
    140     {
    141         return Encrypt(defaultKeyType, plainText, String.Empty,
    142                         String.Empty);
    143     }
    144 
    145     /// <summary>
    146     /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    147     /// string value. This function does not specify data description
    148     /// and additional entropy.
    149     /// </summary>
    150     /// <param name="keyType">
    151     /// Defines type of encryption key to use. When user key is
    152     /// specified, any application running under the same user account
    153     /// as the one making this call, will be able to decrypt data.
    154     /// Machine key will allow any application running on the same
    155     /// computer where data were encrypted to perform decryption.
    156     /// Note: If optional entropy is specifed, it will be required
    157     /// for decryption.
    158     /// </param>
    159     /// <param name="plainText">
    160     /// Plaintext data to be encrypted.
    161     /// </param>
    162     /// <returns>
    163     /// Encrypted value in a base64-encoded format.
    164     /// </returns>
    165     public static string Encrypt(KeyType keyType, string plainText)
    166     {
    167         return Encrypt(keyType, plainText, String.Empty,
    168                         String.Empty);
    169     }
    170 
    171     /// <summary>
    172     /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    173     /// string value. This function does not specify data description.
    174     /// </summary>
    175     /// <param name="keyType">
    176     /// Defines type of encryption key to use. When user key is
    177     /// specified, any application running under the same user account
    178     /// as the one making this call, will be able to decrypt data.
    179     /// Machine key will allow any application running on the same
    180     /// computer where data were encrypted to perform decryption.
    181     /// Note: If optional entropy is specifed, it will be required
    182     /// for decryption.
    183     /// </param>
    184     /// <param name="plainText">
    185     /// Plaintext data to be encrypted.
    186     /// </param>
    187     /// <param name="entropy">
    188     /// Optional entropy which - if specified - will be required to
    189     /// perform decryption.
    190     /// </param>
    191     /// <returns>
    192     /// Encrypted value in a base64-encoded format.
    193     /// </returns>
    194     public static string Encrypt(KeyType keyType,
    195                                  string  plainText,
    196                                  string  entropy)
    197     {
    198         return Encrypt(keyType, plainText, entropy, String.Empty);
    199     }
    200 
    201     /// <summary>
    202     /// Calls DPAPI CryptProtectData function to encrypt a plaintext
    203     /// string value.
    204     /// </summary>
    205     /// <param name="keyType">
    206     /// Defines type of encryption key to use. When user key is
    207     /// specified, any application running under the same user account
    208     /// as the one making this call, will be able to decrypt data.
    209     /// Machine key will allow any application running on the same
    210     /// computer where data were encrypted to perform decryption.
    211     /// Note: If optional entropy is specifed, it will be required
    212     /// for decryption.
    213     /// </param>
    214     /// <param name="plainText">
    215     /// Plaintext data to be encrypted.
    216     /// </param>
    217     /// <param name="entropy">
    218     /// Optional entropy which - if specified - will be required to
    219     /// perform decryption.
    220     /// </param>
    221     /// <param name="description">
    222     /// Optional description of data to be encrypted. If this value is
    223     /// specified, it will be stored along with encrypted data and
    224     /// returned as a separate value during decryption.
    225     /// </param>
    226     /// <returns>
    227     /// Encrypted value in a base64-encoded format.
    228     /// </returns>
    229     public static string Encrypt(KeyType keyType,
    230                                  string  plainText,
    231                                  string  entropy,
    232                                  string  description)
    233     {
    234         // Make sure that parameters are valid.
    235         if (plainText == null) plainText = String.Empty;
    236         if (entropy   == null) entropy   = String.Empty;
    237 
    238         // Call encryption routine and convert returned bytes into
    239         // a base64-encoded value.
    240         return Convert.ToBase64String(
    241                 Encrypt(keyType,
    242                         Encoding.UTF8.GetBytes(plainText),
    243                         Encoding.UTF8.GetBytes(entropy),
    244                         description));
    245     }
    246 
    247     /// <summary>
    248     /// Calls DPAPI CryptProtectData function to encrypt an array of
    249     /// plaintext bytes.
    250     /// </summary>
    251     /// <param name="keyType">
    252     /// Defines type of encryption key to use. When user key is
    253     /// specified, any application running under the same user account
    254     /// as the one making this call, will be able to decrypt data.
    255     /// Machine key will allow any application running on the same
    256     /// computer where data were encrypted to perform decryption.
    257     /// Note: If optional entropy is specifed, it will be required
    258     /// for decryption.
    259     /// </param>
    260     /// <param name="plainTextBytes">
    261     /// Plaintext data to be encrypted.
    262     /// </param>
    263     /// <param name="entropyBytes">
    264     /// Optional entropy which - if specified - will be required to
    265     /// perform decryption.
    266     /// </param>
    267     /// <param name="description">
    268     /// Optional description of data to be encrypted. If this value is
    269     /// specified, it will be stored along with encrypted data and
    270     /// returned as a separate value during decryption.
    271     /// </param>
    272     /// <returns>
    273     /// Encrypted value.
    274     /// </returns>
    275     public static byte[] Encrypt(KeyType keyType,
    276                                  byte[]  plainTextBytes,
    277                                  byte[]  entropyBytes,
    278                                  string  description)
    279     {
    280         // Make sure that parameters are valid.
    281         if (plainTextBytes == null) plainTextBytes = new byte[0];
    282         if (entropyBytes   == null) entropyBytes   = new byte[0];
    283         if (description    == null) description    = String.Empty;
    284 
    285         // Create BLOBs to hold data.
    286         DATA_BLOB plainTextBlob  = new DATA_BLOB();
    287         DATA_BLOB cipherTextBlob = new DATA_BLOB();
    288         DATA_BLOB entropyBlob    = new DATA_BLOB();
    289 
    290         // We only need prompt structure because it is a required
    291         // parameter.
    292         CRYPTPROTECT_PROMPTSTRUCT prompt =
    293                                   new CRYPTPROTECT_PROMPTSTRUCT();
    294         InitPrompt(ref prompt);
    295 
    296         try
    297         {
    298             // Convert plaintext bytes into a BLOB structure.
    299             try
    300             {
    301                 InitBLOB(plainTextBytes, ref plainTextBlob);
    302             }
    303             catch (Exception ex)
    304             {
    305                 throw new Exception(
    306                     "Cannot initialize plaintext BLOB.", ex);
    307             }
    308 
    309             // Convert entropy bytes into a BLOB structure.
    310             try
    311             {
    312                 InitBLOB(entropyBytes, ref entropyBlob);
    313             }
    314             catch (Exception ex)
    315             {
    316                 throw new Exception(
    317                     "Cannot initialize entropy BLOB.", ex);
    318             }
    319 
    320             // Disable any types of UI.
    321             int flags = CRYPTPROTECT_UI_FORBIDDEN;
    322 
    323             // When using machine-specific key, set up machine flag.
    324             if (keyType == KeyType.MachineKey)
    325                 flags |= CRYPTPROTECT_LOCAL_MACHINE;
    326 
    327             // Call DPAPI to encrypt data.
    328             bool success = CryptProtectData(ref plainTextBlob,
    329                                                 description,
    330                                             ref entropyBlob,
    331                                                 IntPtr.Zero,
    332                                             ref prompt,
    333                                                 flags,
    334                                             ref cipherTextBlob);
    335             // Check the result.
    336             if (!success)
    337             {
    338                 // If operation failed, retrieve last Win32 error.
    339                 int errCode = Marshal.GetLastWin32Error();
    340 
    341                 // Win32Exception will contain error message corresponding
    342                 // to the Windows error code.
    343                 throw new Exception(
    344                     "CryptProtectData failed.", new Win32Exception(errCode));
    345             }
    346 
    347             // Allocate memory to hold ciphertext.
    348             byte[] cipherTextBytes = new byte[cipherTextBlob.cbData];
    349 
    350             // Copy ciphertext from the BLOB to a byte array.
    351             Marshal.Copy(cipherTextBlob.pbData,
    352                             cipherTextBytes,
    353                             0,
    354                             cipherTextBlob.cbData);
    355 
    356             // Return the result.
    357             return cipherTextBytes;
    358         }
    359         catch (Exception ex)
    360         {
    361             throw new Exception("DPAPI was unable to encrypt data.", ex);
    362         }
    363         // Free all memory allocated for BLOBs.
    364         finally
    365         {
    366             if (plainTextBlob.pbData != IntPtr.Zero)
    367                 Marshal.FreeHGlobal(plainTextBlob.pbData);
    368 
    369             if (cipherTextBlob.pbData != IntPtr.Zero)
    370                 Marshal.FreeHGlobal(cipherTextBlob.pbData);
    371 
    372             if (entropyBlob.pbData != IntPtr.Zero)
    373                 Marshal.FreeHGlobal(entropyBlob.pbData);
    374         }
    375     }
    376 
    377     /// <summary>
    378     /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    379     /// This function does not use additional entropy and does not
    380     /// return data description.
    381     /// </summary>
    382     /// <param name="cipherText">
    383     /// Encrypted data formatted as a base64-encoded string.
    384     /// </param>
    385     /// <returns>
    386     /// Decrypted data returned as a UTF-8 string.
    387     /// </returns>
    388     /// <remarks>
    389     /// When decrypting data, it is not necessary to specify which
    390     /// type of encryption key to use: user-specific or
    391     /// machine-specific; DPAPI will figure it out by looking at
    392     /// the signature of encrypted data.
    393     /// </remarks>
    394     public static string Decrypt(string cipherText)
    395     {
    396         string description;
    397 
    398         return Decrypt(cipherText, String.Empty, out description);
    399     }
    400 
    401     /// <summary>
    402     /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    403     /// This function does not use additional entropy.
    404     /// </summary>
    405     /// <param name="cipherText">
    406     /// Encrypted data formatted as a base64-encoded string.
    407     /// </param>
    408     /// <param name="description">
    409     /// Returned description of data specified during encryption.
    410     /// </param>
    411     /// <returns>
    412     /// Decrypted data returned as a UTF-8 string.
    413     /// </returns>
    414     /// <remarks>
    415     /// When decrypting data, it is not necessary to specify which
    416     /// type of encryption key to use: user-specific or
    417     /// machine-specific; DPAPI will figure it out by looking at
    418     /// the signature of encrypted data.
    419     /// </remarks>
    420     public static string Decrypt(    string cipherText,
    421                                  out string description)
    422     {
    423         return Decrypt(cipherText, String.Empty, out description);
    424     }
    425 
    426     /// <summary>
    427     /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    428     /// </summary>
    429     /// <param name="cipherText">
    430     /// Encrypted data formatted as a base64-encoded string.
    431     /// </param>
    432     /// <param name="entropy">
    433     /// Optional entropy, which is required if it was specified during
    434     /// encryption.
    435     /// </param>
    436     /// <param name="description">
    437     /// Returned description of data specified during encryption.
    438     /// </param>
    439     /// <returns>
    440     /// Decrypted data returned as a UTF-8 string.
    441     /// </returns>
    442     /// <remarks>
    443     /// When decrypting data, it is not necessary to specify which
    444     /// type of encryption key to use: user-specific or
    445     /// machine-specific; DPAPI will figure it out by looking at
    446     /// the signature of encrypted data.
    447     /// </remarks>
    448     public static string Decrypt(    string cipherText,
    449                                      string entropy,
    450                                  out string description)
    451     {
    452         // Make sure that parameters are valid.
    453         if (entropy == null) entropy = String.Empty;
    454 
    455         return Encoding.UTF8.GetString(
    456                     Decrypt(    Convert.FromBase64String(cipherText),
    457                                 Encoding.UTF8.GetBytes(entropy),
    458                             out description));
    459     }
    460 
    461     /// <summary>
    462     /// Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    463     /// </summary>
    464     /// <param name="cipherTextBytes">
    465     /// Encrypted data.
    466     /// </param>
    467     /// <param name="entropyBytes">
    468     /// Optional entropy, which is required if it was specified during
    469     /// encryption.
    470     /// </param>
    471     /// <param name="description">
    472     /// Returned description of data specified during encryption.
    473     /// </param>
    474     /// <returns>
    475     /// Decrypted data bytes.
    476     /// </returns>
    477     /// <remarks>
    478     /// When decrypting data, it is not necessary to specify which
    479     /// type of encryption key to use: user-specific or
    480     /// machine-specific; DPAPI will figure it out by looking at
    481     /// the signature of encrypted data.
    482     /// </remarks>
    483     public static byte[] Decrypt(    byte[] cipherTextBytes,
    484                                      byte[] entropyBytes,
    485                                  out string description)
    486     {
    487         // Create BLOBs to hold data.
    488         DATA_BLOB plainTextBlob  = new DATA_BLOB();
    489         DATA_BLOB cipherTextBlob = new DATA_BLOB();
    490         DATA_BLOB entropyBlob    = new DATA_BLOB();
    491 
    492         // We only need prompt structure because it is a required
    493         // parameter.
    494         CRYPTPROTECT_PROMPTSTRUCT prompt =
    495                                   new CRYPTPROTECT_PROMPTSTRUCT();
    496         InitPrompt(ref prompt);
    497 
    498         // Initialize description string.
    499         description = String.Empty;
    500 
    501         try
    502         {
    503             // Convert ciphertext bytes into a BLOB structure.
    504             try
    505             {
    506                 InitBLOB(cipherTextBytes, ref cipherTextBlob);
    507             }
    508             catch (Exception ex)
    509             {
    510                 throw new Exception(
    511                     "Cannot initialize ciphertext BLOB.", ex);
    512             }
    513 
    514             // Convert entropy bytes into a BLOB structure.
    515             try
    516             {
    517                 InitBLOB(entropyBytes, ref entropyBlob);
    518             }
    519             catch (Exception ex)
    520             {
    521                 throw new Exception(
    522                     "Cannot initialize entropy BLOB.", ex);
    523             }
    524 
    525             // Disable any types of UI. CryptUnprotectData does not
    526             // mention CRYPTPROTECT_LOCAL_MACHINE flag in the list of
    527             // supported flags so we will not set it up.
    528             int flags = CRYPTPROTECT_UI_FORBIDDEN;
    529 
    530             // Call DPAPI to decrypt data.
    531             bool success = CryptUnprotectData(ref cipherTextBlob,
    532                                               ref description,
    533                                               ref entropyBlob,
    534                                                   IntPtr.Zero,
    535                                               ref prompt,
    536                                                   flags,
    537                                               ref plainTextBlob);
    538 
    539             // Check the result.
    540             if (!success)
    541             {
    542                 // If operation failed, retrieve last Win32 error.
    543                 int errCode = Marshal.GetLastWin32Error();
    544 
    545                 // Win32Exception will contain error message corresponding
    546                 // to the Windows error code.
    547                 throw new Exception(
    548                     "CryptUnprotectData failed.", new Win32Exception(errCode));
    549             }
    550 
    551             // Allocate memory to hold plaintext.
    552             byte[] plainTextBytes = new byte[plainTextBlob.cbData];
    553 
    554             // Copy ciphertext from the BLOB to a byte array.
    555             Marshal.Copy(plainTextBlob.pbData,
    556                          plainTextBytes,
    557                          0,
    558                          plainTextBlob.cbData);
    559 
    560             // Return the result.
    561             return plainTextBytes;
    562         }
    563         catch (Exception ex)
    564         {
    565             throw new Exception("DPAPI was unable to decrypt data.", ex);
    566         }
    567         // Free all memory allocated for BLOBs.
    568         finally
    569         {
    570             if (plainTextBlob.pbData != IntPtr.Zero)
    571                 Marshal.FreeHGlobal(plainTextBlob.pbData);
    572 
    573             if (cipherTextBlob.pbData != IntPtr.Zero)
    574                 Marshal.FreeHGlobal(cipherTextBlob.pbData);
    575 
    576             if (entropyBlob.pbData != IntPtr.Zero)
    577                 Marshal.FreeHGlobal(entropyBlob.pbData);
    578         }
    579     }
    580 }
    581 
    582 /// <summary>
    583 /// Demonstrates the use of DPAPI functions to encrypt and decrypt data.
    584 /// </summary>
    585 public class DPAPITest
    586 {
    587     /// <summary>
    588     /// The main entry point for the application.
    589     /// </summary>
    590     [STAThread]
    591     static void Main(string[] args)
    592     {
    593         try
    594         {
    595             string text    = "Hello, world!";
    596             string entropy = null;
    597             string description;
    598 
    599             Console.WriteLine("Plaintext: {0}\r\n", text);
    600 
    601             // Call DPAPI to encrypt data with user-specific key.
    602             string encrypted = DPAPI.Encrypt( DPAPI.KeyType.UserKey,
    603                                               text,
    604                                               entropy,
    605                                               "My Data");
    606             Console.WriteLine("Encrypted: {0}\r\n", encrypted);
    607 
    608             // Call DPAPI to decrypt data.
    609             string decrypted = DPAPI.Decrypt(   encrypted,
    610                                                 entropy,
    611                                             out description);
    612             Console.WriteLine("Decrypted: {0} <<<{1}>>>\r\n",
    613                                decrypted, description);
    614         }
    615         catch (Exception ex)
    616         {
    617             while (ex != null)
    618             {
    619                 Console.WriteLine(ex.Message);
    620                 ex = ex.InnerException;
    621             }
    622         }
    623     }
    624 }
    625 //
    626 // END OF FILE
    627 ///////////////////////////////////////////////////////////////////////////////
  • 相关阅读:
    第02组 Alpha冲刺(2/6)
    第02组 Alpha冲刺(1/6)
    第02组 团队Git现场编程实战
    第02组 团队项目-需求分析报告
    团队项目-选题报告
    第二次结对编程作业
    第一次结对编程作业
    第2组 团队展示(组长)
    Exchange 2013 中的 OAB (脱机通讯簿)以及如何管理
    vmware esxi 查看网卡、Raid卡驱动
  • 原文地址:https://www.cnblogs.com/jobs2/p/2807072.html
Copyright © 2011-2022 走看看