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

📄 authenticator.cs

📁 使用非对成RSA算法的序列号验证基础库
💻 CS
字号:
using System;
using System.Text;
using System.Security;
using System.Resources;
using System.Management;
using System.Reflection;
using System.Security.Cryptography;

#region 版权声明
///
/// 版权所有(C)2005,2006  作者:漆巧林。保留所有权利, davidqql@gmail.com, davidqql@hotmail.com
/// 
/// 作者不对本代码提供任何保证,因此,对于使用该代码带来的损害或者潜在的损害,作者不承担责任。
/// 在满足如下的条件下,你可以自由使用该代码:
/// 1. 非商业应用
/// 2. 保留本版权声明
/// 要进行商业应用,必须得到作者的书面许可。
/// 你可以修改和自由发布本代码,条件是保留前述的版权声明。
/// 
#endregion


namespace BizSecurity
{
	/// <summary>
	/// 序列号/授权码验证的接口
	/// </summary>
	public interface IAuthenticator
	{
		bool ValidateSerialNumber(string serialNumber);
		string GenerateAuthenticationCode();
		bool ValidateRegistrationCode(string serialNumber, string authCode, string registrationCode);
	}

	/// <summary>
	/// 处理序列号验证接口的类
	/// </summary>
	public class Authenticator : IAuthenticator
	{
		private const int SN_LENGTH = 20;
		private static string symmetricKey;
		private static SimpleRSAProvider rsa;

		static Authenticator()
		{
			ResourceManager rm = new ResourceManager("BizSecurity.Key",Assembly.GetExecutingAssembly());
			// 取得资源
			symmetricKey = rm.GetString("SymmetricKey");
			string modulus = rm.GetString("Modulus");
			string exponentE = rm.GetString("ExponentE");

//			rsa = new SimpleRSAProvider(false, 1024);
//			RSAParameters param = new RSAParameters();
//			param.Modulus = UBigInteger.ConvertStringToByteArray(modulus);
//			param.Exponent = UBigInteger.ConvertStringToByteArray(exponentE);
			UBigInteger mod = UBigInteger.Parse(UBigInteger.ConvertStringToByteArray(modulus));
			UBigInteger e = UBigInteger.Parse(UBigInteger.ConvertStringToByteArray(exponentE));
			rsa = new SimpleRSAProvider(mod, e);
//			rsa.ImportParameters(param);
		}

		public Authenticator()
		{
		}

		public static SimpleRSAProvider RSAProvider
		{
			get { return rsa; }
		}

		/// <summary>
		/// 获取解密之后的对称密钥
		/// </summary>
		private string PlainKey
		{
			get
			{
				byte[] sk = rsa.Encrypt(UBigInteger.ConvertStringToByteArray(symmetricKey));
				return UBigInteger.ConvertByteArrayToString(sk);
			}
		}

		#region IAuthenticator 成员

		/// <summary>
		/// 该方法验证序列号的有效性
		/// </summary>
		/// <param name="serialNumber">序列号</param>
		/// <returns>如果序列号有效,返回true</returns>
		public bool ValidateSerialNumber(string serialNumber)
		{
			// 解密密文得到对称密钥
			string key = this.PlainKey;

			// 序列号必须为20位
			int Len = serialNumber.Length;
			if (Len != SN_LENGTH)
			{
				return false;
			}

			// 解析序列号
			string random = serialNumber.Substring(0, 4);
			string encrypted = serialNumber.Substring(4);
			// 用对称密钥解密
			string decrypted = SymmetricMethod.Decrypt(encrypted, key, ASCIIEncoding.ASCII);
			// 后16位解密后等于前四位
			if (random != decrypted)
			{
				return false;
			}
			return true;
		}

		/// <summary>
		/// 该方法产生验证码
		/// </summary>
		/// <returns>如果没有出现异常,返回生成的验证码</returns>
		public string GenerateAuthenticationCode()
		{
			// 取得机器MAC地址
			string sMacAddress = null;
			ManagementClass mc;
			mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
			ManagementObjectCollection moc = mc.GetInstances();
			foreach(ManagementObject mo in moc)
			{
				if(mo["IPEnabled"].ToString() == "True")
					sMacAddress=mo["MacAddress"].ToString();                    
			}

			// 解密密文得到对称密钥
			string key = this.PlainKey;

			// 连结SN中的前四位同MAC地址,用对称加密为验证码
			string sAuthenticationCode = sMacAddress.Replace(":", "");
			return SymmetricMethod.Encrypt(sAuthenticationCode, key, ASCIIEncoding.ASCII);
		}

		/// <summary>
		/// 该方法根据输入的验证码和注册码验证注册码的有效性
		/// </summary>
		/// <param name="serialNumber">序列号</param>
		/// <param name="authenticationCode">验证码</param>
		/// <param name="registrationCode">注册码</param>
		/// <returns>如果序列号有效,返回true<</returns>
		public bool ValidateRegistrationCode(string serialNumber, string authenticationCode, string registrationCode)
		{
			// 解析密文得到对称密钥
			string key = this.PlainKey;

			// 解析验证码的到机器MAC地址
			string authenticationMac= SymmetricMethod.Decrypt(authenticationCode, key, ASCIIEncoding.ASCII);

			// 取得注册码中有意义的部分
			registrationCode = registrationCode.Substring(32);
			// 解析注册码
			byte[] original = rsa.Encrypt(UBigInteger.ConvertStringToByteArray(registrationCode));
			string registrationDecypt = System.Text.ASCIIEncoding.ASCII.GetString(original);

			// 得到序列号和机器MAC地址
			string registrationSn = registrationDecypt.Substring(0, 4);
			string registrationMac = registrationDecypt.Substring(4, 12);

			// 注册码解析出的序列号必须等于安装所用的序列号
			if (serialNumber.Substring(0, 4) != registrationSn)
			{
				return false;
			}
			// 注册码解析出的机器MAC地址必须等于验证码解析出的机器MAC地址
			if (authenticationMac != registrationMac)
			{
				return false;
			}
			return true;
		}

		/// <summary>
		/// 解析注册码,得到失效日
		/// </summary>
		/// <param name="registrationCode">注册码</param>
		/// <returns>如果没有出现异常,返回得到的失效日</returns>
		public string ParseExpireDate(string registrationCode)
		{
			// 注册码必须大于32位
			if (registrationCode.Length <= 32)
			{
				return string.Empty;
			}

			// 前32位是Hash值
			// 后面部分是用RSA加密的注册信息
			string hashCode = registrationCode.Substring(0, 32);
			string regCode = registrationCode.Substring(32);

			try
			{
				// 注册信息的格式:序列号(4位)+机器MAC(12位)+失效时间(8位)+机器数量(4位)
				// 注册信息必须在24位以上
				byte[] binary = rsa.Encrypt(UBigInteger.ConvertStringToByteArray(regCode));

				if (binary.Length < 12)
				{
					return string.Empty;
				}

				// 计算注册信息的Hash值
				byte[] hashvalue = new MD5CryptoServiceProvider().ComputeHash(binary);
				string hash = BitConverter.ToString(hashvalue);

				// 如果由注册信息计算出的Hash值不等于注册码中前32位的Hash值,则注册码错误
				if (hashCode != hash)
				{
					return string.Empty;
				}

				// 取得失效时间
				return UBigInteger.ConvertByteArrayToString(binary).Substring(16, 8);
			}
			catch(Exception)
			{
				return string.Empty;
			}
		}

		/// <summary>
		/// 解析注册码,得到机器数
		/// </summary>
		/// <param name="registrationCode">注册码</param>
		/// <returns>如果没有出现异常,返回得到的机器数</returns>
		public int ParseSeats(string registrationCode)
		{
			// 注册码必须大于32位
			if (registrationCode.Length <= 32)
			{
				return 0;
			}

			try
			{
				// 解析注册码得到注册码
				// 后面32部分是用RSA加密的注册信息
				byte[] originalReg = rsa.Encrypt(UBigInteger.ConvertStringToByteArray(registrationCode.Substring(32)));

				// 注册信息必须在24位以上
				if (originalReg.Length <= 12)
				{
					return 0;
				}

				// 计算注册信息的Hash值
				// 前32位是Hash值
				byte[] hashCode = UBigInteger.ConvertStringToByteArray(registrationCode.Substring(0, 32));
				byte[] hashvalue = new MD5CryptoServiceProvider().ComputeHash(originalReg);
				if(hashvalue.Length != hashCode.Length)
					return 0;

				// 如果由注册信息计算出的Hash值不等于注册码中前32位的Hash值,则注册码错误
				for(int i=0; i<hashCode.Length; i++)
				{
					if(hashCode[i] != hashvalue[i])
						return 0;
				}

				// 注册信息的格式:序列号(4位)+机器MAC(12位)+失效时间(8位)+机器数量(4位)
				// 取得机器数量
				string origString = System.Text.ASCIIEncoding.ASCII.GetString(originalReg); 
				return int.Parse(origString.Substring(24));
			}
			catch(Exception)
			{
				return 0;
			}
		}

		#endregion
	}
}

⌨️ 快捷键说明

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