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

📄 simplersaprovider.cs

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

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

namespace BizSecurity
{
	/// <summary>
	/// SimpleRSAProvider:简单实现的RSA类
	/// </summary>
	/// <remarks>有关RSA加密之类的信息请参看RFC2437</remarks>
	public class SimpleRSAProvider
	{
		private UBigInteger exponent;	// a prime(一个素数)
		private UBigInteger modulus;	// modulus = p * q
		private UBigInteger d;			// exponent * d % ((p - 1) * (q - 1)) = 1

		private UBigInteger p;			// prime
		private UBigInteger q;			// prime

		private UBigInteger dp;			// e * dp % (p - 1) = 1
		private UBigInteger dq;			// e * dq % (q - 1) = 1
		private UBigInteger qInv;		// q * qInv % p = 1

		private int keySize;

		/// <summary>
		/// 默认构造512位密钥
		/// </summary>
		public SimpleRSAProvider()
			:this(512)
		{
		}

		public SimpleRSAProvider(UBigInteger modulus, UBigInteger exponent)
		{
			this.modulus = modulus;
			this.exponent = exponent;
		}

		/// <summary>
		/// 使用指定的密钥大小初始化新实例,使用.NET的RSACryptoServiceProvider
		/// 创建P和Q,Exponent自动获取随机素数
		/// </summary>
		/// <param name="keySize">密钥大小,以位为单位</param>
		public SimpleRSAProvider(int keySize)
		{
			InitializeByCryptoServiceProvider(keySize);
		}

		private void InitializeByCryptoServiceProvider(int keySize)
		{
			this.keySize = keySize;

			RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize);
			RSAParameters param = rsa.ExportParameters(true);

			p = UBigInteger.Parse(param.P);
			q = UBigInteger.Parse(param.Q);

			ConstructByPQ();
		}

		private void ConstructByPQ()
		{
			modulus = p * q;
			exponent = p.SmallerRandomPrime();	// Let the exponent < p

			UBigInteger leastP = p - 1;
			UBigInteger leastQ = q - 1;
			d = UBigInteger.Euclidean(exponent, leastP * leastQ);

			dp = UBigInteger.Euclidean(exponent, leastP);
			dq = UBigInteger.Euclidean(exponent, leastQ);
			qInv = UBigInteger.Euclidean(q, p);
		}

		/// <summary>
		/// 指示是否按内建CSP構造RSA
		/// </summary>
		/// <param name="fNative">指示是否使用系統内建的CSP,若為真,使用CSP,否則使用UBigInteger大數</param>
		/// <param name="keySize">密鈅大小,以Bit(位)為單位</param>
		public SimpleRSAProvider(bool fNative, int keySize)
		{
			if(fNative)
			{
				this.InitializeByCryptoServiceProvider(keySize);
			}
			else
			{
				p = UBigInteger.RandomPrime(keySize / 32 / 2);
				q = UBigInteger.RandomPrime(keySize / 32 / 2);
				ConstructByPQ();
			}
		}

		/// <summary>
		/// 导入RSA参数
		/// </summary>
		/// <param name="param">要导入的参数,其允许情况如下:
		/// 1. 包含Modulus and Exponent
		/// 2. 包含Modulus and d
		/// 3. 包含p, q, dp, dq, InversQ
		/// 4. 全部参数
		/// 5. p, q, 和/或exponent,如果实例的exponent未定义且没有导入exponent,将出现异常
		/// 6. exponent,如果实例的p, q未定义,将引发异常
		/// </param>
		public void ImportParameters(RSAParameters param)
		{
			// Condition allowed:
			// 1. Modulus and Exmponent
			// 2. Modulus and d
			// 3. p, q, dp, dq, qInv
			// 4. all the fields
			// 5. p, q, exponent
			if(param.D != null && param.P != null && param.Q != null && param.DP != null
				&& param.DQ != null && param.InverseQ != null && param.Exponent != null && param.Modulus != null)
			{
				// validate the data imported
				ImportFullParameters(param);
			}
			else if(param.P != null && param.Q != null && param.DP != null && param.DQ != null && param.InverseQ != null
				&& param.Exponent == null && param.Modulus == null && param.D == null)
			{
				ImportFullPrivateParameters(param);
			}
			else if(param.Modulus != null)
			{
				ImportModulusParameter(param);
			}
			else if(param.P != null && param.Q != null)
			{
				ImportPQParameter(param);
			}
			else if(param.Exponent != null)
			{
				ImportExponentOnly(param);
			}
			else
			{
				throw new CryptographicException("Parameter error");
			}
		}

		/// <summary>
		/// 导出密钥参数
		/// </summary>
		/// <param name="includedPrivateParameters">如果为真,私钥参数也会导出</param>
		/// <returns>返回RSA的参数</returns>
		public RSAParameters ExportParameters(bool includedPrivateParameters)
		{
			RSAParameters param = new RSAParameters();

			if(exponent != null)
				param.Exponent = exponent.ToByteArray();
			if(modulus != null)
				param.Modulus = modulus.ToByteArray();

			if(includedPrivateParameters)
			{
				if(p != null) param.P = p.ToByteArray();
				if(q != null) param.Q = q.ToByteArray();
				if(d != null) param.D = d.ToByteArray();
				if(dp != null) param.DP = dp.ToByteArray();
				if(dq != null) param.DQ = dq.ToByteArray();
				if(qInv != null) param.InverseQ = qInv.ToByteArray();
			}
			return param;
		}

		/// <summary>
		/// 使用私钥进行解密
		/// </summary>
		/// <param name="rgb">密文</param>
		/// <returns>如果解密成功返回明文</returns>
		public byte[] Decrypt(byte[] rgb)
		{
			UBigInteger cipher = UBigInteger.Parse(rgb);
			if(d != null && modulus != null)
			{
				if(cipher >= modulus)
					throw new CryptographicException("The data rgb is invalid, it should be less than modulus!");

				cipher.RSATranslate(d, modulus);
				return cipher.ToByteArray();
			}
			else if(p != null && q != null && dp != null && dq != null)
			{
				// TO this method, it can only handle the condition that m1 > m2
				if(qInv == null)
					qInv = UBigInteger.Euclidean(q, p);
				UBigInteger m1 = UBigInteger.RSATranslate(cipher, dp, p);
				UBigInteger m2 = UBigInteger.RSATranslate(cipher, dq, q);
				m1.Subtraction(m2);
				UBigInteger h = qInv * m1 % p;
				m2.Addition(h);
				return m2.ToByteArray();
			}
			else
			{
				throw new CryptographicException("There's no private key, can not decrypt!");
			}
		}

//		/// <summary>
//		/// 使用私钥进行解密
//		/// </summary>
//		/// <param name="rgb">密文</param>
//		/// <returns>如果解密成功返回明文</returns>
//		public string Decrypt(string rgb)
//		{
//			byte[] decrypt = UBigInteger.ToASCIIByteArray(rgb);
//			// 解密
//			byte[] m = Decrypt(decrypt);
//			return UBigInteger.FromASCIIByteArray(m);
//		}

		/// <summary>
		/// 使用公钥进行加密
		/// </summary>
		/// <param name="rgb">明文</param>
		/// <returns>如果加密成功返回密文</returns>
		public byte[] Encrypt(byte[] rgb)
		{
			UBigInteger biPlainText = UBigInteger.Parse(rgb);
			if(exponent != null && modulus != null)
			{
				if(biPlainText >= modulus)
					throw new CryptographicException("The data rgb is invalid, it should be less than modulus!");

				biPlainText.RSATranslate(exponent, modulus);
				return biPlainText.ToByteArray();
			}
			else
			{
				throw new CryptographicException("There's no public key, can not encrypt data!");
			}
		}

//		/// <summary>
//		/// 使用公钥进行加密
//		/// </summary>
//		/// <param name="rgb">明文</param>
//		/// <returns>如果加密成功返回密文</returns>
//		public string Encrypt(string rgb)
//		{
//			byte[] decrypt = UBigInteger.ToASCIIByteArray(rgb);
//			// 解密
//			byte[] m = Encrypt(decrypt);
//			return UBigInteger.FromASCIIByteArray(m);
//		}

		private UBigInteger ParsePrime(byte[] byteArray, string name)
		{
			UBigInteger prime = UBigInteger.Parse(byteArray);
			if(!prime.PrimalityRabTest())
				throw new CryptographicException(name + " should be a prime");
			return prime;
		}

		private void ImportFullParameters( RSAParameters param )
		{
			UBigInteger pImp = ParsePrime(param.P, "P");
			UBigInteger qImp = ParsePrime(param.Q, "Q");
			UBigInteger exponentImp = ParsePrime(param.Exponent, "Exponent");

			UBigInteger modulusImp = UBigInteger.Parse(param.Modulus);
			if(modulusImp != pImp * qImp)
			{
				throw new CryptographicException("Modulus mismatch p and q param");
			}
			UBigInteger leastP = pImp - 1;
			UBigInteger leastQ = qImp - 1;

			UBigInteger dImp = UBigInteger.Parse(param.D);
			if(dImp != UBigInteger.Euclidean(exponentImp, leastP * leastQ))
				throw new CryptographicException("Import private exponent d error!");

			UBigInteger dpImp = UBigInteger.Parse(param.DP);
			if(dpImp != UBigInteger.Euclidean(exponentImp, leastP))
				throw new CryptographicException("Imported dp error!");

			UBigInteger dqImp = UBigInteger.Parse(param.DQ);
			if(dqImp != UBigInteger.Euclidean(exponentImp, leastQ))
				throw new CryptographicException("Imported dq error!");

			UBigInteger qInvImp = UBigInteger.Parse(param.InverseQ);
			if(qInvImp != UBigInteger.Euclidean(qImp, pImp))
				throw new CryptographicException("Imported InversQ error!");

			p = pImp;
			q = qImp;
			modulus = modulusImp;
			exponent = exponentImp;
			d = dImp;
			dp = dpImp;
			dq = dqImp;
			qInv = qInvImp;
		}

		private void ImportFullPrivateParameters( RSAParameters param )
		{
			UBigInteger pImp = ParsePrime(param.P, "P");
			UBigInteger qImp = ParsePrime(param.Q, "Q");

			UBigInteger dpImp = UBigInteger.Parse(param.DP);
			UBigInteger dqImp = UBigInteger.Parse(param.DQ);
			UBigInteger leastP = pImp - 1;
			UBigInteger leastQ = qImp - 1;

			UBigInteger exponentImp = UBigInteger.Euclidean(dpImp, leastP);
			UBigInteger exponentFromDQ = UBigInteger.Euclidean(dqImp, leastQ);
			UBigInteger qInvImp = UBigInteger.Parse(param.InverseQ);
			if(exponentFromDQ != exponentImp || !exponentImp.PrimalityRabTest()
				|| qInvImp != UBigInteger.Euclidean(qImp, pImp))
				throw new CryptographicException("Error in DP or DQ parameter");

			p = pImp;
			q = qImp;
			dp = dpImp;
			dq = dqImp;
			exponent = exponentImp;
			//d = null;
			d = UBigInteger.Euclidean(exponent, leastP * leastQ);
			qInv = qInvImp;
			modulus = p * q;
		}

		private void RegenerateByPQE( )
		{
			modulus = p * q;
			UBigInteger leastP = p - 1;
			UBigInteger leastQ = q - 1;
			dp = UBigInteger.Euclidean(exponent, leastP);
			dq = UBigInteger.Euclidean(exponent, leastQ);
			d = UBigInteger.Euclidean(exponent, leastP * leastQ);
			qInv = UBigInteger.Euclidean(q, p);
		}

		private void ImportPQParameter( RSAParameters param )
		{
			UBigInteger pImp = ParsePrime(param.P, "P");
			UBigInteger qImp = ParsePrime(param.Q, "Q");
			UBigInteger exponentImp = null;
			if(param.Exponent != null)
				{
					exponentImp = ParsePrime(param.Exponent, "Exponent");
				}
			if(exponent == null && exponentImp == null)
					throw new CryptographicException("Lack of Exponent parameter error!");
			if(exponentImp != null)
					exponent = exponentImp;
			p = pImp;
			q = qImp;
			RegenerateByPQE();
		}

		private void ImportExponentOnly( RSAParameters param )
		{
			UBigInteger exponentImp = ParsePrime(param.Exponent, "Exponent");
			if(p == null || q == null)
					throw new CryptographicException("Import parameter error!");
			RegenerateByPQE();
		}

		private void ImportModulusParameter( RSAParameters param )
		{
			modulus = UBigInteger.Parse(param.Modulus);
			if(param.D != null)
					d = UBigInteger.Parse(param.D);
				else
					d = null;
			if(param.Exponent != null)
					exponent = ParsePrime(param.Exponent, "Exponent");
				else
					exponent = null;
			if(d == null && exponent == null)
					throw new CryptographicException("Incomplete parameter");
			p = null;
			q = null;
			dp = null;
			dq = null;
			qInv = null;
		}
		
	}

	public class BigIntegerException : Exception
	{
		public BigIntegerException()
			: base()
		{
		}

		public BigIntegerException(string s)
			: base(s)
		{
		}
	}
}

⌨️ 快捷键说明

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