[★] DPAPI(Data Protection API) 数据加密和解密

=====================为什么 不能针对中文 ?============
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace CSharpTest
{
    public sealed class DataProtection
    {
        public enum Store
        {
            Machine,
            User
        }
        #region Data Protection API
        //使用了私有类来引用使用的DPAPI
        private class Win32
        {
            //声明了常量
            public const int CRYPTPROTECT_UI_FORBIDDEN = 0x1;
            public const int CRYPTPROTECT_LOCAL_MACHINE = 0x4;
            //声明在DPAPI 中所使用的数据结构
            [StructLayout(LayoutKind.Sequential)]
            public struct DATA_BLOB
            {
                public int cbData;
                public IntPtr pbData;
            }
            //引入CrypproectData 函数
            [DllImport("crypt32", CharSet = CharSet.Auto)]
            public static extern bool CryptProtectData(ref DATA_BLOB pDataIn, string szDataDescr, ref DATA_BLOB pOptionalEntropy, IntPtr pvReserved, IntPtr pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut);

            //引入CryptUnprotectData 函数
            [DllImport("crypt32", CharSet = CharSet.Auto)]
            public static extern bool CryptUnprotectData(ref DATA_BLOB pDataIn, StringBuilder szDataDescr, ref DATA_BLOB pOptionalEntropy, IntPtr pvReserved, IntPtr pPromptStruct, int dwFlags, ref DATA_BLOB pDataOut);
                                    
            //引入 LocalFree 函数
            [DllImport("kernel32")]
            public static extern IntPtr LocalFree(IntPtr hMem);
        }
        #endregion
        /// <summary>
        /// 将数据填充到 DATA_BLOB 结构中,并将数据从托管内存中复制到非托管内存中
        /// </summary>
        /// <param name="blob"></param>
        /// <param name="bits"></param>
        private static void SetBlobData(ref Win32.DATA_BLOB blob, byte[] bits)
        {
            //将数据填充到DATA_BLOB结构中
            blob.cbData = bits.Length;
            blob.pbData = Marshal.AllocHGlobal(bits.Length);
            //将数据从托管内存中复制到非托管内存中
            Marshal.Copy(bits, 0, blob.pbData, bits.Length);
        }
        /// <summary>
        /// 从DATA_BLOB 结构中得到数据,并将数据从非托管代码内存复制到托管内存中
        /// </summary>
        /// <param name="blob"></param>
        /// <returns></returns>
        private static byte [] GetBlobData(ref Win32.DATA_BLOB blob)
        {
            //如果 blob 为空的话, 返回一个空串
            if (blob.pbData.ToInt32() == 0)
                return null;
            //从Data_BlOB 结构中得到数据
            //将数据从非托管内存复制到托管内存中
            byte[] data = new byte[blob.cbData];
            Marshal.Copy(blob.pbData, data, 0, blob.cbData);
            Win32.LocalFree(blob.pbData);
            return data;
        }
        private class Consts
        {
            public readonly static byte[] EntropyData = ASCIIEncoding.ASCII.GetBytes("B0D125B7-967E-4f94-9305-A6F9AF56A19A");
        }
        private DataProtection()
        {
        }
        //使用 DPAPI(Data Protection API) 进行加密,返回值为一个经过Base64编码的字符串
        public static string Encrypt(string data, Store store)
        {
            string result = "";// 结果字符串
            //在 CrypteProtectData 函数调用中使用的blob 变量
            Win32.DATA_BLOB inBlob = new Win32.DATA_BLOB();
            Win32.DATA_BLOB entropyBlob = new Win32.DATA_BLOB();
            Win32.DATA_BLOB outBlob = new Win32.DATA_BLOB();
            try
            {
                //设置调用 CryptProtectData 时使用的标志
                int flags = Win32.CRYPTPROTECT_UI_FORBIDDEN | (int)((store == Store.Machine) ? Win32.CRYPTPROTECT_LOCAL_MACHINE : 0);
                //设置输入的blog 变量,要被加密的blog
                SetBlobData(ref inBlob, ASCIIEncoding.ASCII.GetBytes(data));
                SetBlobData(ref entropyBlob, Consts.EntropyData);

                //调用Dpapi 函数 如果成功的话,函数返回true ,结果将会放入outBlob
                if (Win32.CryptProtectData(ref inBlob, "", ref entropyBlob, IntPtr.Zero, IntPtr.Zero, flags, ref outBlob))
                {
                    //得到 blob 数据
                    byte[] resultBits = GetBlobData(ref outBlob);
                    //转换为 Base64 字符串
                    if (resultBits != null)
                        result = Convert.ToBase64String(resultBits);
                }
            }
            catch(Exception ex)
            {
                throw ex;
                //如果出错,返回一个空字符串\

            }
            finally
            {
                if (inBlob.pbData.ToInt32() != 0)
                    Marshal.FreeHGlobal(inBlob.pbData);
                if (entropyBlob.pbData.ToInt32() != 0)
                    Marshal.FreeHGlobal(entropyBlob.pbData);
            }
            return result;
        }
        //使用  DPAPI(Data Protection API) 进行解密,输入数据是使用Base64进行编码的
        public static string Decrypt(string data, Store store)
        {
            //返回字符串
            string result = "";
            //在CryptUnprotectData 函数调用中使用 blob 变量
            Win32.DATA_BLOB inBlob = new Win32.DATA_BLOB();
            Win32.DATA_BLOB entropyBlob = new Win32.DATA_BLOB();
            Win32.DATA_BLOB outBlob = new Win32.DATA_BLOB();
            try
            {
                int flags = Win32.CRYPTPROTECT_UI_FORBIDDEN | (int)((store==Store.Machine) ? Win32.CRYPTPROTECT_LOCAL_MACHINE :0);
                // 将 Base64 编码后的字符串转化为 byte 数组
                byte[] bits = Convert.FromBase64String(data);
                //设置输入的blob  变量,要被解密的 blob 变量等变量
                SetBlobData(ref inBlob, bits);
                SetBlobData(ref entropyBlob, Consts.EntropyData);

                //调用DPAPI 函数,如果成功就返回 true 结果会填入到 outBlob 去
                if (Win32.CryptUnprotectData(ref inBlob, null, ref entropyBlob, IntPtr.Zero, IntPtr.Zero, flags, ref outBlob))
                {
                    byte[] resultBits = GetBlobData(ref outBlob);
                    //还原为字符串
                    if (resultBits != null)
                        result = ASCIIEncoding.ASCII.GetString(resultBits);
                }

            }
            catch(Exception ex)
            {
                throw ex;
                //如果发生错误,返回一个空的字符串

            }
            finally
            {
                if (inBlob.pbData.ToInt32() != 0)
                    Marshal.FreeHGlobal(inBlob.pbData);
                if (entropyBlob.pbData.ToInt32() != 0)
                    Marshal.FreeHGlobal(entropyBlob.pbData);
                //清理堆数据

            }
            //返回结果
            return result;
        }

    }
}

你可能感兴趣的:(Data)