[★] DPAPI(Data Protection API) 資料加密和解密

來源:互聯網
上載者:User

=====================為什麼 不能針對中文 ?============
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 結構中得到資料,並將資料從Unmanaged 程式碼記憶體複製到託管記憶體中
        /// </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;
                //如果出錯,返回一個Null 字元串\

            }
            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);
                // 將 Base 64 編碼後的字串轉化為 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;
        }

    }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.