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

📄 protecteddata.cs

📁 本源码为OpenNETCF源代码
💻 CS
字号:
//==========================================================================================
//
//		OpenNETCF.Security.Cryptography.ProtectedData
//		Copyright (c) 2003-2004, OpenNETCF.org
//
//		This library is free software; you can redistribute it and/or modify it under 
//		the terms of the OpenNETCF.org Shared Source License.
//
//		This library is distributed in the hope that it will be useful, but 
//		WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
//		FITNESS FOR A PARTICULAR PURPOSE. See the OpenNETCF.org Shared Source License 
//		for more details.
//
//		You should have received a copy of the OpenNETCF.org Shared Source License 
//		along with this library; if not, email licensing@opennetcf.org to request a copy.
//
//		If you wish to contact the OpenNETCF Advisory Board to discuss licensing, please 
//		email licensing@opennetcf.org.
//
//		For general enquiries, email enquiries@opennetcf.org or visit our website at:
//		http://www.opennetcf.org
//
//==========================================================================================
using System;
using System.Runtime.InteropServices;

namespace OpenNETCF.Security.Cryptography
{
	/// <summary>
	/// Specifies the scope of the data protection to be applied by 
	/// the <see cref="OpenNETCF.Security.Cryptography.ProtectedData.Protect"/> method
	/// </summary>
	/// <remarks>
	/// This enumeration is used with the <see cref="OpenNETCF.Security.Cryptography.ProtectedData.Protect"/> and <see cref="OpenNETCF.Security.Cryptography.ProtectedData.Unprotect"/> methods to protect 
	/// data through encryption.
	/// </remarks>
	public enum DataProtectionScope : int
	{
		/// <summary>
		/// Specifies that the protected data is associated with the current user. 
		/// Only threads running under the current user context can unprotect the data.
		/// </summary>
		CurrentUser = 0,
		/// <summary>
		/// Specifies that the protected data is associated with the machine context. 
		/// Any process running under Admin credentials on the computer can unprotect data. 
		/// </summary>
		LocalMachine = 1,
	}

	/// <summary>
	/// Contains methods for protecting and unprotecting data. This class cannot be inherited.
	/// </summary>
	/// <remarks>
	/// The class consists of two wrappers for the unmanaged Data Protection API (DPAPI) methods, 
	/// <see cref="Protect"/> and <see cref="Unprotect"/>. 
	/// These two methods can be used to protect and unprotect data such as passwords, keys, 
	/// and connection strings.
	/// </remarks>
	public sealed class ProtectedData
	{
		private const int CRYPTPROTECT_LOCAL_MACHINE = 0x4;

		/// <summary>
		/// Protects the <c>userData</c> parameter and returns a byte array.
		/// </summary>
		/// <param name="userData">Byte array containing data to be protected.</param>
		/// <param name="optionalEntropy">Additional byte array used to encrypt the data.</param>
		/// <param name="scope">Value from the <see cref="DataProtectionScope"/> enumeration.</param>
		/// <returns>A byte array representing the encrypted data.</returns>
		/// <remarks>
		/// This method can be used to protect data such as passwords, keys, or connection strings. 
		/// The <c>optionalEntropy</c> parameter enables you to use additional information to protect the data.
		/// This information must also be used when unprotecting the data using the <see cref="Unprotect"/> method.
		/// </remarks>
		public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
		{
			byte[] buffer = null;

			CRYPTOAPI_BLOB protectedBlob = new CRYPTOAPI_BLOB();
			GCHandle gchUserData = new GCHandle();
			GCHandle gchEntropy = new GCHandle();

			if(userData == null)
			{
				throw new ArgumentNullException("userData");
			}

			try
			{
				gchUserData = GCHandle.Alloc(userData, GCHandleType.Pinned);
				CRYPTOAPI_BLOB userDataBlob = new CRYPTOAPI_BLOB();
				userDataBlob.cbData = (uint)userData.Length;
				
				userDataBlob.pbData = new IntPtr((int)gchUserData.AddrOfPinnedObject() + 4);

				CRYPTOAPI_BLOB entropyBlob = new CRYPTOAPI_BLOB();
				if(optionalEntropy != null)
				{
					gchEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
					entropyBlob.cbData = (uint)optionalEntropy.Length;
					entropyBlob.pbData = gchEntropy.AddrOfPinnedObject();
				}

				uint flags = 1;
				if(scope == DataProtectionScope.LocalMachine)
				{
					flags = (uint)(flags | CRYPTPROTECT_LOCAL_MACHINE);
				}

				if(!CryptProtectData(ref userDataBlob,string.Empty, ref entropyBlob, IntPtr.Zero,IntPtr.Zero,flags,ref protectedBlob) )
				{
					throw new CryptographicException(Marshal.GetLastWin32Error());
				}
				if(protectedBlob.pbData == IntPtr.Zero)
				{
					throw new OutOfMemoryException();
				}
				
				buffer = new byte[protectedBlob.cbData];
				Marshal.Copy(protectedBlob.pbData, buffer, 0, buffer.Length);
			}	
			finally
			{
				if(gchUserData.IsAllocated)
				{
					gchUserData.Free();
				}

				if(gchEntropy.IsAllocated)
				{
					gchEntropy.Free();
				}

				if(protectedBlob.pbData != IntPtr.Zero)
				{
					ZeroMemory(protectedBlob.pbData, protectedBlob.cbData);
					LocalFree(protectedBlob.pbData);
				}
			}

			return buffer;
		}

		/// <summary>
		/// Unprotects the <c>encryptedData</c> parameter and returns a byte array.
		/// </summary>
		/// <param name="encryptedData">Byte array containing data encrypted with the <see cref="Protect"/> method</param>
		/// <param name="optionalEntropy">Additional byte array that was used to encrypt the data.</param>
		/// <param name="scope">Value from the <see cref="DataProtectionScope"/> enumeration</param>
		/// <returns>A byte array representing the unprotected data.</returns>
		/// <remarks>
		/// This method can be used to unprotect data that was encrypted using the Protect method. 
		/// The <c>optionalEntropy</c> parameter, if used during encryption, must be supplied to unencrypt the data.
		/// </remarks>
		public static byte[] Unprotect(byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope)
		{
			byte[] buffer = null;

			CRYPTOAPI_BLOB unprotectedBlob = new CRYPTOAPI_BLOB();
			GCHandle gchProtectedData = new GCHandle();
			GCHandle gchEntropy = new GCHandle();

			try
			{
				gchProtectedData = GCHandle.Alloc(encryptedData, GCHandleType.Pinned);
				CRYPTOAPI_BLOB protectedBlob = new CRYPTOAPI_BLOB();
				protectedBlob.cbData = (uint)encryptedData.Length;
				
				protectedBlob.pbData = new IntPtr((int)gchProtectedData.AddrOfPinnedObject()+4);
				
				CRYPTOAPI_BLOB entropyBlob = new CRYPTOAPI_BLOB();
				if(optionalEntropy != null)
				{
					gchEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
					entropyBlob.cbData = (uint)optionalEntropy.Length;
					entropyBlob.pbData = gchEntropy.AddrOfPinnedObject();
				}

				uint flags = 1;
				if(scope == DataProtectionScope.LocalMachine)
				{
					flags = (uint)(flags | CRYPTPROTECT_LOCAL_MACHINE);
				}

				if(!CryptUnprotectData(ref protectedBlob,IntPtr.Zero,ref entropyBlob,IntPtr.Zero,IntPtr.Zero,flags,ref unprotectedBlob))
				{
					throw new CryptographicException(Marshal.GetLastWin32Error());
				}
				if(unprotectedBlob.pbData == IntPtr.Zero)
				{
					throw new OutOfMemoryException();
				}

				buffer = new byte[unprotectedBlob.cbData];
				Marshal.Copy(unprotectedBlob.pbData, buffer, 0, buffer.Length);
			}
			finally
			{
				if(gchProtectedData.IsAllocated)
				{
					gchProtectedData.Free();
				}

				if(gchEntropy.IsAllocated)
				{
					gchEntropy.Free();
				}

				if(unprotectedBlob.pbData != IntPtr.Zero)
				{
					ZeroMemory(unprotectedBlob.pbData,unprotectedBlob.cbData);
					LocalFree(unprotectedBlob.pbData);
				}
			}

			return buffer;
		}

		#region Native Methods

		[DllImport("Coredll.dll",SetLastError=true)]
		static extern bool CryptProtectData
			(
			ref CRYPTOAPI_BLOB pDataIn,
			string szDataDescr,
			ref CRYPTOAPI_BLOB pOptionalEntropy,
			IntPtr pvReserved,
			IntPtr pPromptStruct,
			uint dwFlags,
			ref CRYPTOAPI_BLOB pDataOut
			);

		[DllImport("Coredll.dll",SetLastError=true)]
		static extern bool CryptUnprotectData
			(
			ref CRYPTOAPI_BLOB pDataIn,
			IntPtr ppszDataDescr,
			ref CRYPTOAPI_BLOB Entropy,
			IntPtr pvReserved,
			IntPtr pPromptStruct,
			uint dwFlags,
			ref CRYPTOAPI_BLOB pDataOut
			);

		[DllImport("Coredll.dll")]
		static extern void memset(IntPtr pbData, uint offset, uint cbData);

		[DllImport("Coredll.dll")]
		static extern void LocalFree(IntPtr pbData);

		static void ZeroMemory(IntPtr pbData, uint cbData)
		{
			memset(pbData,0,cbData);
		}

		#endregion
		
		struct CRYPTOAPI_BLOB
		{
			public uint cbData;
			public IntPtr pbData;
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -