=====================为什么 不能针对中文 ?============
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;
}
}
}