// <summary> /// Window自带加密解密DPAPI /// </summary> public class DPAPI { #region /// <summary> /// DPAPI加密 /// </summary> /// <param name="pPlainText"></param> /// <param name="szDescription"></param> /// <param name="pEntropy"></param> /// <param name="pReserved"></param> /// <param name="pPrompt"></param> /// <param name="dwFlags"></param> /// <param name="pCipherText"></param> /// <returns></returns> [DllImport("crypt32.dll", EntryPoint = "CryptProtectData", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] public static extern bool DPAPIEncrypt(ref DATA_BLOB pPlainText, string szDescription, ref DATA_BLOB pEntropy, IntPtr pReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPrompt, int dwFlags, ref DATA_BLOB pCipherText); /// <summary> /// DPAPI解密 /// </summary> /// <param name="pCipherText"></param> /// <param name="pszDescription"></param> /// <param name="pEntropy"></param> /// <param name="pReserved"></param> /// <param name="pPrompt"></param> /// <param name="dwFlags"></param> /// <param name="pPlainText"></param> /// <returns></returns> [DllImport("crypt32.dll", EntryPoint = "CryptUnprotectData", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] public static extern bool DPAPIDecrypt(ref DATA_BLOB pCipherText, ref string pszDescription, ref DATA_BLOB pEntropy, IntPtr pReserved, ref CRYPTPROTECT_PROMPTSTRUCT pPrompt, int dwFlags, ref DATA_BLOB pPlainText); #endregion #region /// <summary> /// 密钥类型 /// </summary> public enum KeyType { /// <summary> /// 用户存储 /// </summary> UserKey = 1, /// <summary> /// 机器存储 /// </summary> MachineKey }; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DATA_BLOB { public int cbData; public IntPtr pbData; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct CRYPTPROTECT_PROMPTSTRUCT { public int cbSize; public int dwPromptFlags; public IntPtr hwndApp; public string szPrompt; } private static IntPtr NullPtr = ((IntPtr)((int)(0))); private static KeyType defaultKeyType = KeyType.UserKey; private const int CRYPTPROTECT_UI_FORBIDDEN = 0x1; private const int CRYPTPROTECT_LOCAL_MACHINE = 0x4; #endregion private static void InitPrompt(ref CRYPTPROTECT_PROMPTSTRUCT ps) { ps.cbSize = Marshal.SizeOf(typeof(CRYPTPROTECT_PROMPTSTRUCT)); ps.dwPromptFlags = 0; ps.hwndApp = NullPtr; ps.szPrompt = null; } private static void InitBLOB(byte[] data, ref DATA_BLOB blob) { blob.pbData = Marshal.AllocHGlobal(data.Length); if (blob.pbData == IntPtr.Zero) throw new Exception("无法为BLOB结构分配数据缓冲区"); blob.cbData = data.Length; Marshal.Copy(data, 0, blob.pbData, data.Length); } /// <summary> /// 加密 /// </summary> /// <param name="plainText">要加密明文</param> /// <returns></returns> public static string Encrypt(string plainText) { return Encrypt(defaultKeyType, plainText, String.Empty, String.Empty); } /// <summary> /// 加密 /// </summary> /// <param name="keyType">密钥类型</param> /// <param name="plainText">要加密明文</param> /// <returns></returns> public static string Encrypt(KeyType keyType, string plainText) { return Encrypt(keyType, plainText, String.Empty, String.Empty); } /// <summary> /// 加密 /// </summary> /// <param name="keyType">密钥类型</param> /// <param name="plainText">要加密明文</param> /// <param name="entropy"></param> /// <returns></returns> public static string Encrypt(KeyType keyType, string plainText, string entropy) { return Encrypt(keyType, plainText, entropy, String.Empty); } /// <summary> /// 加密 /// </summary> /// <param name="keyType">密钥类型</param> /// <param name="plainText">要加密明文</param> /// <param name="entropy"></param> /// <param name="description"></param> /// <returns></returns> public static string Encrypt(KeyType keyType, string plainText, string entropy, string description) { if (plainText == null) plainText = String.Empty; if (entropy == null) entropy = String.Empty; return Convert.ToBase64String(Encrypt(keyType, Encoding.UTF8.GetBytes(plainText), Encoding.UTF8.GetBytes(entropy), description)); } /// <summary> /// 加密 /// </summary> /// <param name="keyType">密钥类型</param> /// <param name="plainTextBytes">要加密明文</param> /// <param name="entropyBytes"></param> /// <param name="description"></param> /// <returns></returns> public static byte[] Encrypt(KeyType keyType, byte[] plainTextBytes, byte[] entropyBytes, string description) { if (plainTextBytes == null) plainTextBytes = new byte[0]; if (entropyBytes == null) entropyBytes = new byte[0]; if (description == null) description = String.Empty; DATA_BLOB plainTextBlob = new DATA_BLOB(); DATA_BLOB cipherTextBlob = new DATA_BLOB(); DATA_BLOB entropyBlob = new DATA_BLOB(); CRYPTPROTECT_PROMPTSTRUCT prompt = new CRYPTPROTECT_PROMPTSTRUCT(); InitPrompt(ref prompt); try { try { InitBLOB(plainTextBytes, ref plainTextBlob);//将明文字节转换为BLOB结构。 } catch (Exception ex) { throw new Exception("无法初始化纯文本BLOB", ex); } try { InitBLOB(entropyBytes, ref entropyBlob);//将熵字节转换为BLOB结构 } catch (Exception ex) { throw new Exception("无法初始化熵BLOB。", ex); } int flags = CRYPTPROTECT_UI_FORBIDDEN; if (keyType == KeyType.MachineKey) flags |= CRYPTPROTECT_LOCAL_MACHINE; bool success = DPAPIEncrypt(ref plainTextBlob, description, ref entropyBlob, IntPtr.Zero, ref prompt, flags, ref cipherTextBlob); if (!success) { throw new Exception("CryptProtectData失败", new Win32Exception(Marshal.GetLastWin32Error())); } byte[] cipherTextBytes = new byte[cipherTextBlob.cbData]; Marshal.Copy(cipherTextBlob.pbData, cipherTextBytes, 0, cipherTextBlob.cbData); return cipherTextBytes; } catch (Exception ex) { throw new Exception("DPAPI无法加密数据", ex); } finally { if (plainTextBlob.pbData != IntPtr.Zero) Marshal.FreeHGlobal(plainTextBlob.pbData); if (cipherTextBlob.pbData != IntPtr.Zero) Marshal.FreeHGlobal(cipherTextBlob.pbData); if (entropyBlob.pbData != IntPtr.Zero) Marshal.FreeHGlobal(entropyBlob.pbData); } } /// <summary> /// 解密 /// </summary> /// <param name="cipherText">要解密的密文</param> /// <returns></returns> public static string Decrypt(string cipherText) { string description; return Decrypt(cipherText, String.Empty, out description); } /// <summary> /// 解密 /// </summary> /// <param name="cipherText">要解密的密文</param> /// <param name="description"></param> /// <returns></returns> public static string Decrypt(string cipherText, out string description) { return Decrypt(cipherText, String.Empty, out description); } /// <summary> /// 解密 /// </summary> /// <param name="cipherText">要解密的密文</param> /// <param name="entropy"></param> /// <param name="description"></param> /// <returns></returns> public static string Decrypt(string cipherText, string entropy, out string description) { if (entropy == null) entropy = String.Empty; return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(cipherText), Encoding.UTF8.GetBytes(entropy), out description)); } /// <summary> /// 解密 /// </summary> /// <param name="cipherTextBytes">要解密的密文</param> /// <param name="entropyBytes"></param> /// <param name="description"></param> /// <returns></returns> public static byte[] Decrypt(byte[] cipherTextBytes, byte[] entropyBytes, out string description) { DATA_BLOB plainTextBlob = new DATA_BLOB(); DATA_BLOB cipherTextBlob = new DATA_BLOB(); DATA_BLOB entropyBlob = new DATA_BLOB(); CRYPTPROTECT_PROMPTSTRUCT prompt = new CRYPTPROTECT_PROMPTSTRUCT(); InitPrompt(ref prompt); description = String.Empty; try { try { InitBLOB(cipherTextBytes, ref cipherTextBlob); } catch (Exception ex) { throw new Exception("无法初始化密文BLOB", ex); } try { InitBLOB(entropyBytes, ref entropyBlob); } catch (Exception ex) { throw new Exception("无法初始化熵BLOB", ex); } int flags = CRYPTPROTECT_UI_FORBIDDEN; bool success = DPAPIDecrypt(ref cipherTextBlob, ref description, ref entropyBlob, IntPtr.Zero, ref prompt, flags, ref plainTextBlob); if (!success) { throw new Exception("CryptUnprotectData失败", new Win32Exception(Marshal.GetLastWin32Error())); } byte[] plainTextBytes = new byte[plainTextBlob.cbData]; Marshal.Copy(plainTextBlob.pbData, plainTextBytes, 0, plainTextBlob.cbData); return plainTextBytes; } catch (Exception ex) { throw new Exception("DPAPI无法解密数据", ex); } finally { if (plainTextBlob.pbData != IntPtr.Zero) Marshal.FreeHGlobal(plainTextBlob.pbData); if (cipherTextBlob.pbData != IntPtr.Zero) Marshal.FreeHGlobal(cipherTextBlob.pbData); if (entropyBlob.pbData != IntPtr.Zero) Marshal.FreeHGlobal(entropyBlob.pbData); } } }