⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dataprotection.cs

📁 文件保护 文件保护 文件保护
💻 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 + -