📄 dataprotection.cs
字号:
//***************************************************************************
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This code sample is provided "AS IS" without warranty of any kind.
//
//***************************************************************************
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace DocumentProtector
{
#region NativeMethods Class
internal static class NativeMethods
{
#region DataProtection API Imports/Structures/Flags
#region DataProtection API Methods
/// <summary>
/// Performs encryption on the data in a DATA_BLOB structure.
/// </summary>
/// <param name="dataIn">
/// Pointer to a DATA_BLOB structure containing
/// the plaintext to be encrypted.
/// </param>
/// <param name="szDataDescr">
/// String with a readable description of the data to be encrypted.
/// </param>
/// <param name="optionalEntropy">
/// Pointer to a DATA_BLOB structure that contains a password or
/// other additional entropy used to encrypt the data.
/// </param>
/// <param name="pvReserved">
/// Reserved for future use and must be set to NULL.
/// </param>
/// <param name="pPromptStruct">
/// Pointer to a CRYPTPROTECT_PROMPTSTRUCT structure that provides
/// information about where and when prompts are to be displayed and
/// what the content of those prompts should be.
/// </param>
/// <param name="dwFlags">
/// Flags to use when encrypting the plaintext.
/// </param>
/// <param name="pDataOut">
/// Pointer to a DATA_BLOB structure that receives the encrypted data.
/// </param>
/// <returns>
/// If the function succeeds, the return value is true.
/// If the function fails, the return value is false.
/// </returns>
[DllImport("crypt32", CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
internal static extern bool CryptProtectData(ref DATA_BLOB dataIn, string szDataDescr, IntPtr optionalEntropy, IntPtr pvReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut);
/// <summary>
/// Decrypts and does an integrity check of the data
/// in a DATA_BLOB structure.
/// </summary>
/// <param name="dataIn">
/// Pointer to a DATA_BLOB structure that holds the encrypted data.
/// </param>
/// <param name="ppszDataDescr">
/// Pointer to a string readable description of the encrypted data
/// included with the encrypted data is placed
/// </param>
/// <param name="optionalEntropy">
/// Pointer to a DATA_BLOB structure containing a password or other
/// additional entropy used when the data was encrypted.
/// </param>
/// <param name="pvReserved">
/// Reserved for future use and must be set to NULL.
/// </param>
/// <param name="pPromptStruct">
/// Pointer to a CRYPTPROTECT_PROMPTSTRUCT structure that provides
/// information about where and when prompts are to be displayed and
/// what the content of those prompts should be.
/// </param>
/// <param name="dwFlags">
/// Flags to use when dencrypting the text.
/// </param>
/// <param name="pDataOut">
/// Pointer to a DATA_BLOB structure where the function
/// stores the decrypted data.
/// </param>
/// <returns>
/// If the function succeeds, the return value is TRUE.
/// If the function fails, the return value is FALSE.
/// </returns>
[DllImport("crypt32", CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
internal static extern bool CryptUnprotectData(ref DATA_BLOB dataIn, StringBuilder ppszDataDescr, IntPtr optionalEntropy, IntPtr pvReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut);
/// <summary>
/// Frees the specified local memory object and invalidates its handle.
/// </summary>
/// <param name="hMem">
/// Handle to the local memory object.
/// </param>
/// <returns>
/// If the function succeeds, the return value is NULL.
/// If the function fails, the return value is equal to
/// a handle to the local memory object.
/// </returns>
[DllImport("kernel32")]
internal static extern IntPtr LocalFree(IntPtr hMem);
#endregion
#region DataProtection API Structures
/// <summary>
/// Structure used by the CryptoAPI for arbitrary array of bytes.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct DATA_BLOB
{
/// <summary>
/// Count of bytes in the buffer pointed to by pbData.
/// </summary>
internal int cbData;
/// <summary>
/// Pointer to a block of data bytes.
/// </summary>
internal IntPtr pbData;
}
/// <summary>
/// Provides the text of a prompt and information
/// about when and where that prompt is to be displayed.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct CRYPTPROTECT_PROMPTSTRUCT
{
/// <summary>
/// Size of this structure in bytes.
/// </summary>
internal int cbSize;
/// <summary>
/// DWORD flags that indicate when prompts
/// to the user are to be displayed.
/// </summary>
internal int dwPromptFlags;
/// <summary>
/// Window handle to the parent window.
/// </summary>
internal IntPtr hwndApp;
/// <summary>
/// A string containing the text of a prompt to be displayed.
/// </summary>
internal string szPrompt;
}
#endregion
#region DataProtection API Flags
/// <summary>
/// This flag is used to provide the prompt for the protect phase.
/// </summary>
internal const int PromptOnProtect = 0x2;
/// <summary>
/// This flag can be combined with PromptOnProtect
/// to enforce the UI (user interface) policy of the caller.
/// </summary>
internal const int PromptOnUnprotect = 0x1;
/// <summary>
/// Wsed for remote situations where presenting a
/// user interface (UI) is not an option.
/// </summary>
internal const int UIForbidden = 0x1;
/// <summary>
/// Set the default user security level to strong.
/// </summary>
internal const int PromptStrong = 0x08;
/// <summary>
/// Associates the data encrypted with the current
/// computer instead of with an individual user.
/// </summary>
internal const int LocalMachine = 0x4;
/// <summary>
/// When this flag is used, no data is actually protected.
/// </summary>
internal const int CredSync = 0x8;
/// <summary>
/// This flag generates an audit on protect and unprotect operations.
/// </summary>
internal const int Audit = 0x10;
/// <summary>
/// This flag verifies the protection of a protected BLOB.
/// </summary>
internal const int VerifyProtection = 0x40;
#endregion
#endregion
}
#endregion
#region DataProtection Class
/// <summary>
/// Provides methods to encrypt/decrypt strings using the DPAPI.
/// </summary>
public static class DataProtection
{
#region Public DataProtection Methods
/// <summary>
/// Encrypts the given data using the DataProtection API.
/// </summary>
/// <param name="data">The string data to encrypt.</param>
/// <param name="name">Description of the data to encrypt.</param>
/// <returns>The encrypted string value.</returns>
public static string ProtectData(string data, string name)
{
if (data == null)
throw new ArgumentNullException("data");
if (name == null)
throw new ArgumentNullException("name");
byte[] dataIn = Encoding.Unicode.GetBytes(data);
byte[] dataOut = ProtectData(dataIn, name, NativeMethods.UIForbidden);
if (dataOut != null)
return Convert.ToBase64String(dataOut);
else
return null;
}
/// <summary>
/// Decrypts the given data using the DataProtection API.
/// </summary>
/// <param name="data">The string data to decrypt.</param>
/// <returns>The decrypted string value.</returns>
public static string UnprotectData(string data)
{
if (data == null)
throw new ArgumentNullException("data");
byte[] dataIn = Convert.FromBase64String(data);
byte[] dataOut = UnprotectData(dataIn,
NativeMethods.UIForbidden | NativeMethods.VerifyProtection);
if (dataOut != null)
return Encoding.Unicode.GetString(dataOut);
else
return null;
}
#endregion
#region Helper Methods
/// <summary>
/// Protects the data using the DataProtection API.
/// </summary>
/// <param name="data">Data to encrypt.</param>
/// <param name="name">Description of data to encrypt.</param>
/// <param name="dwFlags">Flags to use when encrypting the data.</param>
/// <returns>Encrypted version of the data.</returns>
private static byte[] ProtectData(byte[] data, string name, int dwFlags)
{
byte[] cipherText = null;
// Copy data into unmanaged memory.
NativeMethods.DATA_BLOB din = new NativeMethods.DATA_BLOB();
din.cbData = data.Length;
din.pbData = Marshal.AllocHGlobal(din.cbData);
Marshal.Copy(data, 0, din.pbData, din.cbData);
// Fill the DPAPI prompt structure.
NativeMethods.DATA_BLOB dout = new NativeMethods.DATA_BLOB();
NativeMethods.CRYPTPROTECT_PROMPTSTRUCT ps = new NativeMethods.CRYPTPROTECT_PROMPTSTRUCT();
InitPromptStruct(ref ps);
try
{
// Encrypt the data.
bool ret = NativeMethods.CryptProtectData(ref din, name, IntPtr.Zero,
IntPtr.Zero, ref ps, dwFlags, ref dout);
if (ret)
{
// If the encryption worked, copy the data.
cipherText = new byte[dout.cbData];
Marshal.Copy(dout.pbData, cipherText, 0, dout.cbData);
NativeMethods.LocalFree(dout.pbData);
}
}
finally
{
// Perform cleanup.
if (din.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(din.pbData);
}
return cipherText;
}
/// <summary>
/// Unprotects data using the DataProtection API.
/// </summary>
/// <param name="data">Data to decrypt.</param>
/// <param name="dwFlags">Flags to use when decrypting the data.</param>
/// <returns>Decrypted version of the data.</returns>
private static byte[] UnprotectData(byte[] data, int dwFlags)
{
byte[] clearText = null;
// Copy data into unmanaged memory.
NativeMethods.DATA_BLOB din = new NativeMethods.DATA_BLOB();
din.cbData = data.Length;
din.pbData = Marshal.AllocHGlobal(din.cbData);
Marshal.Copy(data, 0, din.pbData, din.cbData);
// Fill the DPAPI prompt structure.
NativeMethods.DATA_BLOB dout = new NativeMethods.DATA_BLOB();
NativeMethods.CRYPTPROTECT_PROMPTSTRUCT ps = new NativeMethods.CRYPTPROTECT_PROMPTSTRUCT();
InitPromptStruct(ref ps);
try
{
// Decrypt the data.
bool ret = NativeMethods.CryptUnprotectData(ref din, null, IntPtr.Zero,
IntPtr.Zero, ref ps, dwFlags, ref dout);
if (ret)
{
// If decryption worked, copy the data.
clearText = new byte[dout.cbData];
Marshal.Copy(dout.pbData, clearText, 0, dout.cbData);
NativeMethods.LocalFree(dout.pbData);
}
}
finally
{
// Perform cleanup.
if (din.pbData != IntPtr.Zero)
Marshal.FreeHGlobal(din.pbData);
}
return clearText;
}
/// <summary>
/// Initializes the structure with default values.
/// </summary>
/// <param name="ps">The structure to initialize.</param>
private static void InitPromptStruct(ref NativeMethods.CRYPTPROTECT_PROMPTSTRUCT ps)
{
ps.cbSize = Marshal.SizeOf(typeof(NativeMethods.CRYPTPROTECT_PROMPTSTRUCT));
ps.dwPromptFlags = 0;
ps.hwndApp = IntPtr.Zero;
ps.szPrompt = null;
}
#endregion
}
#endregion
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -