新年新气象,也希望新年可以挣大钱。不管今年年底会不会跟去年一样,满怀抱负却又壮志未酬。(不过没事,我已为各位卜上一卦,卦象显示各位都能挣钱...)。已经上班两天了,公司大部分人还在休假,而我早已上班,估计今年我就是加班狗的命。(不说了,要坚强...)

以上扯淡已毕,下面言归正传。

这次的.NET加密解析系列中,前面已经讲解了散列加密、对称加密、数字签名三种加密方式,在这篇博文种,将会主要讲解非对称加密的原理,以及非对称加密在.NET种的应用。

一.非对称加密概述:

前面讲解过对称加密,对称加密中加密和解密的密钥是相同的,但是正因为如此,这会给协商过程带来潜在的危险。所以产生了非对称加密方式。

1.非对称加密原理概述:

非对称加密算法需要两个密钥,分别是公钥和私钥。公钥和私钥是一对,如果公钥对数据进行加密,只有使用私钥才可以进行解密,反之亦然。对于非对称加密的原理有如下图:

以上是大致说明了消息利用非对称加密和解密的方式,解析来我们再来看一下如果生成密钥对。非对称加密算法包含一个“密钥生成”协议,用户可以使用该协议生成密钥对。有如下图:

在非对称加密算法中,使用两个有关的函数,一个是加密函数,使用一个公钥加密消息,加密函数只能加密数据;一个时解密函数,使用一个私钥来解密被响应公钥加密的消息。

2.非对称加密特点概述:

非对称加密算法中,采用加密函数和解密函数,加密函数只能加密函数,解密函数只能解密函数。加密函数的单向性意味着一个发送者创建的消息不能被另一个发送者阅读。非对称加密相对于对称加密来说,非对称加密的速度非常慢,而且不适用于加密大量数据,公钥加密(非对称加密)是用来为对称加密算法解决密钥协商的问题而产生的。RSA算法中指定密钥长度为最小的位数,这些位的个数使用二进制数表示密钥系数N的值。

3.非对称加密算法分类概述:

对于非对称加密算法的种类,有如下图:

RSA算法:此算法是基于数论的非对称密码体制,采用分组加密方式。安全性是基于大整数因子分解的困难性,RSA算法是第一个既能用于数据加密也能用与数字签名的算法。

DSA算法(数字签名算法):次算法是基于证书有限域离散对数难题。

ECC算法(椭圆曲线密码体制):椭圆曲线指的是由维尔斯特拉斯方程所确定的平面曲线。

Diffie-Hellman算法:该算法本身限于密钥交换的用途,目的在于使得两个用户安全地交换一个秘密密钥以便用与以后的报文加密。该算法依赖于计算离散对数的难度。

以上是简单介绍了一些算法,没有更加深入的介绍其算法原理,由于涉及的知识面比较广,分析起来比较的繁琐,在这里就不做讲解,如果有兴趣可以自行学习和了解。

二.DotNet非对称加密核心对象解析:

上面简单叙述了非对称加密的原理,在这里主要介绍非对称加密算法在.NET种的应用,以及实现该算法所创建的对象。在这里主要介绍RSA算法的核心对象。

1.RSA加密和解密的方式:

2.DotNet种RSA算法核心对象概述:

在.NET种对于非对称加密算法的结构体系有如下图:

3.AsymmetricAlgorithm类解析:

(1).Create():创建用于执行非对称算法的默认加密对象。

  1. public static AsymmetricAlgorithm Create()
  2. {
  3. return AsymmetricAlgorithm.Create("System.Security.Cryptography.AsymmetricAlgorithm");
  4. }

该方法返回新的 RSACryptoServiceProvider 实例,除非已使用 <cryptoClass> 元素更改默认设置。

  1. public static AsymmetricAlgorithm Create(string algName)
  2. {
  3. return (AsymmetricAlgorithm) CryptoConfig.CreateFromName(algName);
  4. }

该方法返回所指定的非对称算法实现的新实例。接收参数为要使用的非对称算法实现。CryptoConfig.CreateFromName()该方法在前面的加密方式中已经做过解析,这里就不做介绍了。

(2).KeySize:获取或设置非对称算法所用密钥模块的大小(以位为单位)。

  1. public virtual int KeySize
  2. {
  3. get
  4. {
  5. return this.KeySizeValue;
  6. }
  7. set
  8. {
  9. for (int index = ; index < this.LegalKeySizesValue.Length; ++index)
  10. {
  11. if (this.LegalKeySizesValue[index].SkipSize == )
  12. {
  13. if (this.LegalKeySizesValue[index].MinSize == value)
  14. {
  15. this.KeySizeValue = value;
  16. return;
  17. }
  18. }
  19. else
  20. {
  21. int minSize = this.LegalKeySizesValue[index].MinSize;
  22. while (minSize <= this.LegalKeySizesValue[index].MaxSize)
  23. {
  24. if (minSize == value)
  25. {
  26. this.KeySizeValue = value;
  27. return;
  28. }
  29. minSize += this.LegalKeySizesValue[index].SkipSize;
  30. }
  31. }
  32. }
  33. throw new CryptographicException(Environment.GetResourceString("Cryptography_InvalidKeySize"));
  34. }
  35. }

由以上代码可以发现,该属性具有get和set两个构造器,说明该属性是可读可写的。该属性返回非对称算法所用密钥模块的大小(以位为单位)。

4.RSA类解析:

(1).FromXmlString():通过 XML 字符串中的密钥信息初始化Cryptography.RSA对象。

  1. public override void FromXmlString(string xmlString)
  2. {
  3. if (xmlString == null)
  4. throw new ArgumentNullException("xmlString");
  5. RSAParameters parameters = new RSAParameters();
  6. SecurityElement topElement = new Parser(xmlString).GetTopElement();
  7. string inputBuffer1 = topElement.SearchForTextOfLocalName("Modulus");
  8. if (inputBuffer1 == null)
  9. {
  10. string key = "Cryptography_InvalidFromXmlString";
  11. object[] objArray = new object[];
  12. int index1 = ;
  13. string str1 = "RSA";
  14. objArray[index1] = (object) str1;
  15. int index2 = ;
  16. string str2 = "Modulus";
  17. objArray[index2] = (object) str2;
  18. throw new CryptographicException(Environment.GetResourceString(key, objArray));
  19. }
  20. parameters.Modulus = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer1));
  21. string inputBuffer2 = topElement.SearchForTextOfLocalName("Exponent");
  22. if (inputBuffer2 == null)
  23. {
  24. string key = "Cryptography_InvalidFromXmlString";
  25. object[] objArray = new object[];
  26. int index1 = ;
  27. string str1 = "RSA";
  28. objArray[index1] = (object) str1;
  29. int index2 = ;
  30. string str2 = "Exponent";
  31. objArray[index2] = (object) str2;
  32. throw new CryptographicException(Environment.GetResourceString(key, objArray));
  33. }
  34. parameters.Exponent = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer2));
  35. string inputBuffer3 = topElement.SearchForTextOfLocalName("P");
  36. if (inputBuffer3 != null)
  37. parameters.P = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer3));
  38. string inputBuffer4 = topElement.SearchForTextOfLocalName("Q");
  39. if (inputBuffer4 != null)
  40. parameters.Q = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer4));
  41. string inputBuffer5 = topElement.SearchForTextOfLocalName("DP");
  42. if (inputBuffer5 != null)
  43. parameters.DP = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer5));
  44. string inputBuffer6 = topElement.SearchForTextOfLocalName("DQ");
  45. if (inputBuffer6 != null)
  46. parameters.DQ = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer6));
  47. string inputBuffer7 = topElement.SearchForTextOfLocalName("InverseQ");
  48. if (inputBuffer7 != null)
  49. parameters.InverseQ = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer7));
  50. string inputBuffer8 = topElement.SearchForTextOfLocalName("D");
  51. if (inputBuffer8 != null)
  52. parameters.D = Convert.FromBase64String(Utils.DiscardWhiteSpaces(inputBuffer8));
  53. this.ImportParameters(parameters);
  54. }

该方法是继承自AsymmetricAlgorithm类,在RSA类种被重写,该方法接收参数包含 RSA 密钥信息的 XML 字符串。SecurityElement类表示用于编码安全对象的XML对象模型。

(2).ToXmlString():创建并返回包含当前 RSA 对象的密钥的 XML 字符串。

  1. public override string ToXmlString(bool includePrivateParameters)
  2. {
  3. RSAParameters rsaParameters = this.ExportParameters(includePrivateParameters);
  4. StringBuilder stringBuilder = new StringBuilder();
  5. stringBuilder.Append("<RSAKeyValue>");
  6. stringBuilder.Append("<Modulus>" + Convert.ToBase64String(rsaParameters.Modulus) + "</Modulus>");
  7. stringBuilder.Append("<Exponent>" + Convert.ToBase64String(rsaParameters.Exponent) + "</Exponent>");
  8. if (includePrivateParameters)
  9. {
  10. stringBuilder.Append("<P>" + Convert.ToBase64String(rsaParameters.P) + "</P>");
  11. stringBuilder.Append("<Q>" + Convert.ToBase64String(rsaParameters.Q) + "</Q>");
  12. stringBuilder.Append("<DP>" + Convert.ToBase64String(rsaParameters.DP) + "</DP>");
  13. stringBuilder.Append("<DQ>" + Convert.ToBase64String(rsaParameters.DQ) + "</DQ>");
  14. stringBuilder.Append("<InverseQ>" + Convert.ToBase64String(rsaParameters.InverseQ) + "</InverseQ>");
  15. stringBuilder.Append("<D>" + Convert.ToBase64String(rsaParameters.D) + "</D>");
  16. }
  17. stringBuilder.Append("</RSAKeyValue>");
  18. return stringBuilder.ToString();
  19. }

该方法同样继承自AsymmetricAlgorithm类,该方法接收一个布尔型的参数,true 表示同时包含 RSA 公钥和私钥;false 表示仅包含公钥。该方法返回包含当前 RSA 对象的密钥的 XML 字符串。RSAParameters为一个结构,表示System.Security.Cryptography.RSA算法的标准参数。

5.RSACryptoServiceProvider类解析:

(1).Encrypt():使用 RSA算法对数据进行加密。

  1. [SecuritySafeCritical]
  2. public byte[] Encrypt(byte[] rgb, bool fOAEP)
  3. {
  4. if (rgb == null)
  5. throw new ArgumentNullException("rgb");
  6. this.GetKeyPair();
  7. byte[] o = (byte[]) null;
  8. RSACryptoServiceProvider.EncryptKey(this._safeKeyHandle, rgb, rgb.Length, fOAEP, JitHelpers.GetObjectHandleOnStack<byte[]>(ref o));
  9. return o;
  10. }

该方法接受两个参数,要加密的数据。fOAEP如果为 true,则使用 OAEP 填充(仅在运行 Microsoft Windows XP 或更高版本的计算机上可用)执行直接的 RSA 加密;否则,如果为 false,则使用 PKCS#1 1.5 版填充。该方法返回一个已加密的数据,为一个字节数组。

(2).Decrypt():使用 RSA算法对数据进行解密。

  1. [SecuritySafeCritical]
  2. public byte[] Decrypt(byte[] rgb, bool fOAEP)
  3. {
  4. if (rgb == null)
  5. throw new ArgumentNullException("rgb");
  6. this.GetKeyPair();
  7. if (rgb.Length > this.KeySize / )
  8. {
  9. string key = "Cryptography_Padding_DecDataTooBig";
  10. object[] objArray = new object[];
  11. int index = ;
  12. // ISSUE: variable of a boxed type
  13. __Boxed<int> local = (ValueType) (this.KeySize / );
  14. objArray[index] = (object) local;
  15. throw new CryptographicException(Environment.GetResourceString(key, objArray));
  16. }
  17. if (!this.CspKeyContainerInfo.RandomlyGenerated && !CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
  18. {
  19. KeyContainerPermission containerPermission = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
  20. KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(this._parameters, KeyContainerPermissionFlags.Decrypt);
  21. containerPermission.AccessEntries.Add(accessEntry);
  22. containerPermission.Demand();
  23. }
  24. byte[] o = (byte[]) null;
  25. RSACryptoServiceProvider.DecryptKey(this._safeKeyHandle, rgb, rgb.Length, fOAEP, JitHelpers.GetObjectHandleOnStack<byte[]>(ref o));
  26. return o;
  27. }

该方法接受两个参数,rgb要解密的数据。fOAEP如果为 true,则使用 OAEP 填充(仅在运行 Microsoft Windows XP 或更高版本的计算机上可用)执行直接的 <see cref="T:System.Security.Cryptography.RSA"/> 解密;否则,如果为 false,则使用 PKCS#1 1.5 版填充。该方法返回 已解密的数据,它是加密前的原始纯文本。

三.应用实例:

1.RsaHelper类:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Security.Cryptography;
  5. using System.Text;
  6.  
  7. namespace BasicMmethodExtensionClass.EncryptHelper
  8. {
  9. /// <summary>
  10. /// 非对称RSA加密类
  11. /// 需要BigInteger类来辅助
  12. /// </summary>
  13. public static class RsaHelper
  14. {
  15. /// <summary>
  16. /// RSA的容器 可以解密的源字符串长度为 DWKEYSIZE/8-11
  17. /// </summary>
  18. public const int Dwkeysize = ;
  19.  
  20. /// <summary>
  21. /// RSA加密的密匙结构 公钥和私匙
  22. /// </summary>
  23. public struct RsaKey
  24. {
  25. public string PublicKey { get; set; }
  26.  
  27. public string PrivateKey { get; set; }
  28. }
  29.  
  30. /// <summary>
  31. /// 得到RSA的解谜的密匙对
  32. /// </summary>
  33. /// <returns></returns>
  34. public static RsaKey GetRasKey()
  35. {
  36. RSACryptoServiceProvider.UseMachineKeyStore = true;
  37. //声明一个指定大小的RSA容器
  38. RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(Dwkeysize);
  39. //取得RSA容易里的各种参数
  40. RSAParameters p = rsaProvider.ExportParameters(true);
  41.  
  42. return new RsaKey
  43. {
  44. PublicKey = ComponentKey(p.Exponent, p.Modulus),
  45. PrivateKey = ComponentKey(p.D, p.Modulus)
  46. };
  47. }
  48.  
  49. /// <summary>
  50. /// 检查明文的有效性 DWKEYSIZE/8-11 长度之内为有效 中英文都算一个字符
  51. /// </summary>
  52. /// <param name="source"></param>
  53. /// <returns></returns>
  54. public static bool CheckSourceValidate(string source)
  55. {
  56. return (Dwkeysize / - ) >= source.Length;
  57. }
  58.  
  59. /// <summary>
  60. /// 组合成密匙字符串
  61. /// </summary>
  62. /// <param name="b1"></param>
  63. /// <param name="b2"></param>
  64. /// <returns></returns>
  65. private static string ComponentKey(byte[] b1, byte[] b2)
  66. {
  67. var list = new List<byte>
  68. {
  69. (byte) b1.Length
  70. };
  71. list.AddRange(b1);
  72. list.AddRange(b2);
  73. var b = list.ToArray<byte>();
  74. return Convert.ToBase64String(b);
  75. }
  76.  
  77. /// <summary>
  78. /// 解析密匙
  79. /// </summary>
  80. /// <param name="key">密匙</param>
  81. /// <param name="b1">RSA的相应参数1</param>
  82. /// <param name="b2">RSA的相应参数2</param>
  83. private static void ResolveKey(string key, out byte[] b1, out byte[] b2)
  84. {
  85. //从base64字符串 解析成原来的字节数组
  86. byte[] b = Convert.FromBase64String(key);
  87. //初始化参数的数组长度
  88. b1 = new byte[b[]];
  89. b2 = new byte[b.Length - b[] - ];
  90. //将相应位置是值放进相应的数组
  91. for (int n = , i = , j = ; n < b.Length; n++)
  92. {
  93. if (n <= b[])
  94. {
  95. b1[i++] = b[n];
  96. }
  97. else
  98. {
  99. b2[j++] = b[n];
  100. }
  101. }
  102. }
  103.  
  104. /// <summary>
  105. /// 字符串加密
  106. /// </summary>
  107. /// <param name="source">源字符串 明文</param>
  108. /// <param name="key">密匙</param>
  109. /// <returns>加密遇到错误将会返回原字符串</returns>
  110. public static string EncryptString(string source, string key)
  111. {
  112. string encryptString;
  113. try
  114. {
  115. if (!CheckSourceValidate(source))
  116. {
  117. throw new Exception("明文太长");
  118. }
  119. //解析这个密钥
  120. byte[] d;
  121. byte[] n;
  122. ResolveKey(key, out d, out n);
  123. var biN = new BigInteger(n);
  124. var biD = new BigInteger(d);
  125. encryptString = EncryptString(source, biD, biN);
  126. }
  127. catch
  128. {
  129. encryptString = source;
  130. }
  131. return encryptString;
  132. }
  133.  
  134. /// <summary>
  135. /// 字符串解密
  136. /// </summary>
  137. /// <param name="encryptString">密文</param>
  138. /// <param name="key">密钥</param>
  139. /// <returns>遇到解密失败将会返回原字符串</returns>
  140. public static string DecryptString(string encryptString, string key)
  141. {
  142. string source;
  143. try
  144. {
  145. //解析这个密钥
  146. byte[] e;
  147. byte[] n;
  148. ResolveKey(key, out e, out n);
  149. var biE = new BigInteger(e);
  150. var biN = new BigInteger(n);
  151. source = DecryptString(encryptString, biE, biN);
  152. }
  153. catch
  154. {
  155. source = encryptString;
  156. }
  157. return source;
  158. }
  159.  
  160. /// <summary>
  161. /// 用指定的密匙加密
  162. /// </summary>
  163. /// <param name="source">明文</param>
  164. /// <param name="d">可以是RSACryptoServiceProvider生成的D</param>
  165. /// <param name="n">可以是RSACryptoServiceProvider生成的Modulus</param>
  166. /// <returns>返回密文</returns>
  167. private static string EncryptString(string source, BigInteger d, BigInteger n)
  168. {
  169. var len = source.Length;
  170. int len1;
  171. if ((len % ) == )
  172. len1 = len / ;
  173. else
  174. len1 = len / + ;
  175. var result = new StringBuilder();
  176. for (var i = ; i < len1; i++)
  177. {
  178. var blockLen = len >= ? : len;
  179. var block = source.Substring(i * , blockLen);
  180. byte[] oText = Encoding.UTF8.GetBytes(block);
  181. var biText = new BigInteger(oText);
  182. var biEnText = biText.modPow(d, n);
  183. var temp = biEnText.ToHexString();
  184. result.Append(temp).Append("@");
  185. len -= blockLen;
  186. }
  187. return result.ToString().TrimEnd('@');
  188. }
  189.  
  190. /// <summary>
  191. /// 用指定的密匙加密
  192. /// </summary>
  193. /// <param name="encryptString"></param>
  194. /// <param name="e">可以是RSACryptoServiceProvider生成的Exponent</param>
  195. /// <param name="n">可以是RSACryptoServiceProvider生成的Modulus</param>
  196. /// <returns>返回明文</returns>
  197. private static string DecryptString(string encryptString, BigInteger e, BigInteger n)
  198. {
  199. var result = new StringBuilder();
  200. var strarr1 = encryptString.Split(new[] { '@' }, StringSplitOptions.RemoveEmptyEntries);
  201. foreach (var block in strarr1)
  202. {
  203. var biText = new BigInteger(block, );
  204. var biEnText = biText.modPow(e, n);
  205. var temp = Encoding.UTF8.GetString(biEnText.getBytes());
  206. result.Append(temp);
  207. }
  208. return result.ToString();
  209. }
  210. }
  211. }

2.BigInteger类:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace BasicMmethodExtensionClass.EncryptHelper
  8. {
  9. public class BigInteger
  10. {
  11. // maximum length of the BigInteger in uint (4 bytes)
  12. // change this to suit the required level of precision.
  13.  
  14. private const int maxLength = ;
  15.  
  16. // primes smaller than 2000 to test the generated prime number
  17.  
  18. public static readonly int[] primesBelow2000 = {
  19. , , , , , , , , , , , , , , , , , , , , , , , , ,
  20. , , , , , , , , , , , , , , , , , , , , ,
  21. , , , , , , , , , , , , , , , ,
  22. , , , , , , , , , , , , , , , ,
  23. , , , , , , , , , , , , , , , , ,
  24. , , , , , , , , , , , , , ,
  25. , , , , , , , , , , , , , , , ,
  26. , , , , , , , , , , , , , ,
  27. , , , , , , , , , , , , , , ,
  28. , , , , , , , , , , , , , ,
  29. , , , , , , , , , , , , , , , ,
  30. , , , , , , , , , , , ,
  31. , , , , , , , , , , , , , , ,
  32. , , , , , , , , , , ,
  33. , , , , , , , , , , , , , , , , ,
  34. , , , , , , , , , , , ,
  35. , , , , , , , , , , , , , , ,
  36. , , , , , , , , , , , ,
  37. , , , , , , , , , , , ,
  38. , , , , , , , , , , , , };
  39.  
  40. private uint[] data; // stores bytes from the Big Integer
  41. public int DataLength; // number of actual chars used
  42.  
  43. //***********************************************************************
  44. // Constructor (Default value for BigInteger is 0
  45. //***********************************************************************
  46.  
  47. public BigInteger()
  48. {
  49. data = new uint[maxLength];
  50. DataLength = ;
  51. }
  52.  
  53. //***********************************************************************
  54. // Constructor (Default value provided by long)
  55. //***********************************************************************
  56.  
  57. public BigInteger(long value)
  58. {
  59. data = new uint[maxLength];
  60. long tempVal = value;
  61.  
  62. // copy bytes from long to BigInteger without any assumption of
  63. // the length of the long datatype
  64.  
  65. DataLength = ;
  66. while (value != && DataLength < maxLength)
  67. {
  68. data[DataLength] = (uint)(value & 0xFFFFFFFF);
  69. value >>= ;
  70. DataLength++;
  71. }
  72.  
  73. if (tempVal > ) // overflow check for +ve value
  74. {
  75. if (value != || (data[maxLength - ] & 0x80000000) != )
  76. throw (new ArithmeticException("Positive overflow in constructor."));
  77. }
  78. else if (tempVal < ) // underflow check for -ve value
  79. {
  80. if (value != - || (data[DataLength - ] & 0x80000000) == )
  81. throw (new ArithmeticException("Negative underflow in constructor."));
  82. }
  83.  
  84. if (DataLength == )
  85. DataLength = ;
  86. }
  87.  
  88. //***********************************************************************
  89. // Constructor (Default value provided by ulong)
  90. //***********************************************************************
  91.  
  92. public BigInteger(ulong value)
  93. {
  94. data = new uint[maxLength];
  95.  
  96. // copy bytes from ulong to BigInteger without any assumption of
  97. // the length of the ulong datatype
  98.  
  99. DataLength = ;
  100. while (value != && DataLength < maxLength)
  101. {
  102. data[DataLength] = (uint)(value & 0xFFFFFFFF);
  103. value >>= ;
  104. DataLength++;
  105. }
  106.  
  107. if (value != || (data[maxLength - ] & 0x80000000) != )
  108. throw (new ArithmeticException("Positive overflow in constructor."));
  109.  
  110. if (DataLength == )
  111. DataLength = ;
  112. }
  113.  
  114. //***********************************************************************
  115. // Constructor (Default value provided by BigInteger)
  116. //***********************************************************************
  117.  
  118. public BigInteger(BigInteger bi)
  119. {
  120. data = new uint[maxLength];
  121.  
  122. DataLength = bi.DataLength;
  123.  
  124. for (int i = ; i < DataLength; i++)
  125. data[i] = bi.data[i];
  126. }
  127.  
  128. //***********************************************************************
  129. // Constructor (Default value provided by a string of digits of the
  130. // specified base)
  131. //
  132. // Example (base 10)
  133. // -----------------
  134. // To initialize "a" with the default value of 1234 in base 10
  135. // BigInteger a = new BigInteger("1234", 10)
  136. //
  137. // To initialize "a" with the default value of -1234
  138. // BigInteger a = new BigInteger("-1234", 10)
  139. //
  140. // Example (base 16)
  141. // -----------------
  142. // To initialize "a" with the default value of 0x1D4F in base 16
  143. // BigInteger a = new BigInteger("1D4F", 16)
  144. //
  145. // To initialize "a" with the default value of -0x1D4F
  146. // BigInteger a = new BigInteger("-1D4F", 16)
  147. //
  148. // Note that string values are specified in the <sign><magnitude>
  149. // format.
  150. //
  151. //***********************************************************************
  152.  
  153. public BigInteger(string value, int radix)
  154. {
  155. BigInteger multiplier = new BigInteger();
  156. BigInteger result = new BigInteger();
  157. value = (value.ToUpper()).Trim();
  158. int limit = ;
  159.  
  160. if (value[] == '-')
  161. limit = ;
  162.  
  163. for (int i = value.Length - ; i >= limit; i--)
  164. {
  165. int posVal = (int)value[i];
  166.  
  167. if (posVal >= '' && posVal <= '')
  168. posVal -= '';
  169. else if (posVal >= 'A' && posVal <= 'Z')
  170. posVal = (posVal - 'A') + ;
  171. else
  172. posVal = ; // arbitrary large
  173.  
  174. if (posVal >= radix)
  175. throw (new ArithmeticException("Invalid string in constructor."));
  176. else
  177. {
  178. if (value[] == '-')
  179. posVal = -posVal;
  180.  
  181. result = result + (multiplier * posVal);
  182.  
  183. if ((i - ) >= limit)
  184. multiplier = multiplier * radix;
  185. }
  186. }
  187.  
  188. if (value[] == '-') // negative values
  189. {
  190. if ((result.data[maxLength - ] & 0x80000000) == )
  191. throw (new ArithmeticException("Negative underflow in constructor."));
  192. }
  193. else // positive values
  194. {
  195. if ((result.data[maxLength - ] & 0x80000000) != )
  196. throw (new ArithmeticException("Positive overflow in constructor."));
  197. }
  198.  
  199. data = new uint[maxLength];
  200. for (int i = ; i < result.DataLength; i++)
  201. data[i] = result.data[i];
  202.  
  203. DataLength = result.DataLength;
  204. }
  205.  
  206. //***********************************************************************
  207. // Constructor (Default value provided by an array of bytes)
  208. //
  209. // The lowest index of the input byte array (i.e [0]) should contain the
  210. // most significant byte of the number, and the highest index should
  211. // contain the least significant byte.
  212. //
  213. // E.g.
  214. // To initialize "a" with the default value of 0x1D4F in base 16
  215. // byte[] temp = { 0x1D, 0x4F };
  216. // BigInteger a = new BigInteger(temp)
  217. //
  218. // Note that this method of initialization does not allow the
  219. // sign to be specified.
  220. //
  221. //***********************************************************************
  222.  
  223. public BigInteger(byte[] inData)
  224. {
  225. DataLength = inData.Length >> ;
  226.  
  227. int leftOver = inData.Length & 0x3;
  228. if (leftOver != ) // length not multiples of 4
  229. DataLength++;
  230.  
  231. if (DataLength > maxLength)
  232. throw (new ArithmeticException("Byte overflow in constructor."));
  233.  
  234. data = new uint[maxLength];
  235.  
  236. for (int i = inData.Length - , j = ; i >= ; i -= , j++)
  237. {
  238. data[j] = (uint)((inData[i - ] << ) + (inData[i - ] << ) +
  239. (inData[i - ] << ) + inData[i]);
  240. }
  241.  
  242. if (leftOver == )
  243. data[DataLength - ] = (uint)inData[];
  244. else if (leftOver == )
  245. data[DataLength - ] = (uint)((inData[] << ) + inData[]);
  246. else if (leftOver == )
  247. data[DataLength - ] = (uint)((inData[] << ) + (inData[] << ) + inData[]);
  248.  
  249. while (DataLength > && data[DataLength - ] == )
  250. DataLength--;
  251.  
  252. //Console.WriteLine("Len = " + dataLength);
  253. }
  254.  
  255. //***********************************************************************
  256. // Constructor (Default value provided by an array of bytes of the
  257. // specified length.)
  258. //***********************************************************************
  259.  
  260. public BigInteger(byte[] inData, int inLen)
  261. {
  262. DataLength = inLen >> ;
  263.  
  264. int leftOver = inLen & 0x3;
  265. if (leftOver != ) // length not multiples of 4
  266. DataLength++;
  267.  
  268. if (DataLength > maxLength || inLen > inData.Length)
  269. throw (new ArithmeticException("Byte overflow in constructor."));
  270.  
  271. data = new uint[maxLength];
  272.  
  273. for (int i = inLen - , j = ; i >= ; i -= , j++)
  274. {
  275. data[j] = (uint)((inData[i - ] << ) + (inData[i - ] << ) +
  276. (inData[i - ] << ) + inData[i]);
  277. }
  278.  
  279. if (leftOver == )
  280. data[DataLength - ] = (uint)inData[];
  281. else if (leftOver == )
  282. data[DataLength - ] = (uint)((inData[] << ) + inData[]);
  283. else if (leftOver == )
  284. data[DataLength - ] = (uint)((inData[] << ) + (inData[] << ) + inData[]);
  285.  
  286. if (DataLength == )
  287. DataLength = ;
  288.  
  289. while (DataLength > && data[DataLength - ] == )
  290. DataLength--;
  291.  
  292. //Console.WriteLine("Len = " + dataLength);
  293. }
  294.  
  295. //***********************************************************************
  296. // Constructor (Default value provided by an array of unsigned integers)
  297. //*********************************************************************
  298.  
  299. public BigInteger(uint[] inData)
  300. {
  301. DataLength = inData.Length;
  302.  
  303. if (DataLength > maxLength)
  304. throw (new ArithmeticException("Byte overflow in constructor."));
  305.  
  306. data = new uint[maxLength];
  307.  
  308. for (int i = DataLength - , j = ; i >= ; i--, j++)
  309. data[j] = inData[i];
  310.  
  311. while (DataLength > && data[DataLength - ] == )
  312. DataLength--;
  313.  
  314. //Console.WriteLine("Len = " + dataLength);
  315. }
  316.  
  317. //***********************************************************************
  318. // Overloading of the typecast operator.
  319. // For BigInteger bi = 10;
  320. //***********************************************************************
  321.  
  322. public static implicit operator BigInteger(long value)
  323. {
  324. return (new BigInteger(value));
  325. }
  326.  
  327. public static implicit operator BigInteger(ulong value)
  328. {
  329. return (new BigInteger(value));
  330. }
  331.  
  332. public static implicit operator BigInteger(int value)
  333. {
  334. return (new BigInteger((long)value));
  335. }
  336.  
  337. public static implicit operator BigInteger(uint value)
  338. {
  339. return (new BigInteger((ulong)value));
  340. }
  341.  
  342. //***********************************************************************
  343. // Overloading of addition operator
  344. //***********************************************************************
  345.  
  346. public static BigInteger operator +(BigInteger bi1, BigInteger bi2)
  347. {
  348. BigInteger result = new BigInteger();
  349.  
  350. result.DataLength = (bi1.DataLength > bi2.DataLength) ? bi1.DataLength : bi2.DataLength;
  351.  
  352. long carry = ;
  353. for (int i = ; i < result.DataLength; i++)
  354. {
  355. long sum = (long)bi1.data[i] + (long)bi2.data[i] + carry;
  356. carry = sum >> ;
  357. result.data[i] = (uint)(sum & 0xFFFFFFFF);
  358. }
  359.  
  360. if (carry != && result.DataLength < maxLength)
  361. {
  362. result.data[result.DataLength] = (uint)(carry);
  363. result.DataLength++;
  364. }
  365.  
  366. while (result.DataLength > && result.data[result.DataLength - ] == )
  367. result.DataLength--;
  368.  
  369. // overflow check
  370. int lastPos = maxLength - ;
  371. if ((bi1.data[lastPos] & 0x80000000) == (bi2.data[lastPos] & 0x80000000) &&
  372. (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
  373. {
  374. throw (new ArithmeticException());
  375. }
  376.  
  377. return result;
  378. }
  379.  
  380. //***********************************************************************
  381. // Overloading of the unary ++ operator
  382. //***********************************************************************
  383.  
  384. public static BigInteger operator ++(BigInteger bi1)
  385. {
  386. BigInteger result = new BigInteger(bi1);
  387.  
  388. long val, carry = ;
  389. int index = ;
  390.  
  391. while (carry != && index < maxLength)
  392. {
  393. val = (long)(result.data[index]);
  394. val++;
  395.  
  396. result.data[index] = (uint)(val & 0xFFFFFFFF);
  397. carry = val >> ;
  398.  
  399. index++;
  400. }
  401.  
  402. if (index > result.DataLength)
  403. result.DataLength = index;
  404. else
  405. {
  406. while (result.DataLength > && result.data[result.DataLength - ] == )
  407. result.DataLength--;
  408. }
  409.  
  410. // overflow check
  411. int lastPos = maxLength - ;
  412.  
  413. // overflow if initial value was +ve but ++ caused a sign
  414. // change to negative.
  415.  
  416. if ((bi1.data[lastPos] & 0x80000000) == &&
  417. (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
  418. {
  419. throw (new ArithmeticException("Overflow in ++."));
  420. }
  421. return result;
  422. }
  423.  
  424. //***********************************************************************
  425. // Overloading of subtraction operator
  426. //***********************************************************************
  427.  
  428. public static BigInteger operator -(BigInteger bi1, BigInteger bi2)
  429. {
  430. BigInteger result = new BigInteger();
  431.  
  432. result.DataLength = (bi1.DataLength > bi2.DataLength) ? bi1.DataLength : bi2.DataLength;
  433.  
  434. long carryIn = ;
  435. for (int i = ; i < result.DataLength; i++)
  436. {
  437. long diff;
  438.  
  439. diff = (long)bi1.data[i] - (long)bi2.data[i] - carryIn;
  440. result.data[i] = (uint)(diff & 0xFFFFFFFF);
  441.  
  442. if (diff < )
  443. carryIn = ;
  444. else
  445. carryIn = ;
  446. }
  447.  
  448. // roll over to negative
  449. if (carryIn != )
  450. {
  451. for (int i = result.DataLength; i < maxLength; i++)
  452. result.data[i] = 0xFFFFFFFF;
  453. result.DataLength = maxLength;
  454. }
  455.  
  456. // fixed in v1.03 to give correct datalength for a - (-b)
  457. while (result.DataLength > && result.data[result.DataLength - ] == )
  458. result.DataLength--;
  459.  
  460. // overflow check
  461.  
  462. int lastPos = maxLength - ;
  463. if ((bi1.data[lastPos] & 0x80000000) != (bi2.data[lastPos] & 0x80000000) &&
  464. (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
  465. {
  466. throw (new ArithmeticException());
  467. }
  468.  
  469. return result;
  470. }
  471.  
  472. //***********************************************************************
  473. // Overloading of the unary -- operator
  474. //***********************************************************************
  475.  
  476. public static BigInteger operator --(BigInteger bi1)
  477. {
  478. BigInteger result = new BigInteger(bi1);
  479.  
  480. long val;
  481. bool carryIn = true;
  482. int index = ;
  483.  
  484. while (carryIn && index < maxLength)
  485. {
  486. val = (long)(result.data[index]);
  487. val--;
  488.  
  489. result.data[index] = (uint)(val & 0xFFFFFFFF);
  490.  
  491. if (val >= )
  492. carryIn = false;
  493.  
  494. index++;
  495. }
  496.  
  497. if (index > result.DataLength)
  498. result.DataLength = index;
  499.  
  500. while (result.DataLength > && result.data[result.DataLength - ] == )
  501. result.DataLength--;
  502.  
  503. // overflow check
  504. int lastPos = maxLength - ;
  505.  
  506. // overflow if initial value was -ve but -- caused a sign
  507. // change to positive.
  508.  
  509. if ((bi1.data[lastPos] & 0x80000000) != &&
  510. (result.data[lastPos] & 0x80000000) != (bi1.data[lastPos] & 0x80000000))
  511. {
  512. throw (new ArithmeticException("Underflow in --."));
  513. }
  514.  
  515. return result;
  516. }
  517.  
  518. //***********************************************************************
  519. // Overloading of multiplication operator
  520. //***********************************************************************
  521.  
  522. public static BigInteger operator *(BigInteger bi1, BigInteger bi2)
  523. {
  524. int lastPos = maxLength - ;
  525. bool bi1Neg = false, bi2Neg = false;
  526.  
  527. // take the absolute value of the inputs
  528. try
  529. {
  530. if ((bi1.data[lastPos] & 0x80000000) != ) // bi1 negative
  531. {
  532. bi1Neg = true; bi1 = -bi1;
  533. }
  534. if ((bi2.data[lastPos] & 0x80000000) != ) // bi2 negative
  535. {
  536. bi2Neg = true; bi2 = -bi2;
  537. }
  538. }
  539. catch (Exception) { }
  540.  
  541. BigInteger result = new BigInteger();
  542.  
  543. // multiply the absolute values
  544. try
  545. {
  546. for (int i = ; i < bi1.DataLength; i++)
  547. {
  548. if (bi1.data[i] == ) continue;
  549.  
  550. ulong mcarry = ;
  551. for (int j = , k = i; j < bi2.DataLength; j++, k++)
  552. {
  553. // k = i + j
  554. ulong val = ((ulong)bi1.data[i] * (ulong)bi2.data[j]) +
  555. (ulong)result.data[k] + mcarry;
  556.  
  557. result.data[k] = (uint)(val & 0xFFFFFFFF);
  558. mcarry = (val >> );
  559. }
  560.  
  561. if (mcarry != )
  562. result.data[i + bi2.DataLength] = (uint)mcarry;
  563. }
  564. }
  565. catch (Exception)
  566. {
  567. throw (new ArithmeticException("Multiplication overflow."));
  568. }
  569.  
  570. result.DataLength = bi1.DataLength + bi2.DataLength;
  571. if (result.DataLength > maxLength)
  572. result.DataLength = maxLength;
  573.  
  574. while (result.DataLength > && result.data[result.DataLength - ] == )
  575. result.DataLength--;
  576.  
  577. // overflow check (result is -ve)
  578. if ((result.data[lastPos] & 0x80000000) != )
  579. {
  580. if (bi1Neg != bi2Neg && result.data[lastPos] == 0x80000000) // different sign
  581. {
  582. // handle the special case where multiplication produces
  583. // a max negative number in 2's complement.
  584.  
  585. if (result.DataLength == )
  586. return result;
  587. else
  588. {
  589. bool isMaxNeg = true;
  590. for (int i = ; i < result.DataLength - && isMaxNeg; i++)
  591. {
  592. if (result.data[i] != )
  593. isMaxNeg = false;
  594. }
  595.  
  596. if (isMaxNeg)
  597. return result;
  598. }
  599. }
  600.  
  601. throw (new ArithmeticException("Multiplication overflow."));
  602. }
  603.  
  604. // if input has different signs, then result is -ve
  605. if (bi1Neg != bi2Neg)
  606. return -result;
  607.  
  608. return result;
  609. }
  610.  
  611. //***********************************************************************
  612. // Overloading of unary << operators
  613. //***********************************************************************
  614.  
  615. public static BigInteger operator <<(BigInteger bi1, int shiftVal)
  616. {
  617. BigInteger result = new BigInteger(bi1);
  618. result.DataLength = shiftLeft(result.data, shiftVal);
  619.  
  620. return result;
  621. }
  622.  
  623. // least significant bits at lower part of buffer
  624.  
  625. private static int shiftLeft(uint[] buffer, int shiftVal)
  626. {
  627. int shiftAmount = ;
  628. int bufLen = buffer.Length;
  629.  
  630. while (bufLen > && buffer[bufLen - ] == )
  631. bufLen--;
  632.  
  633. for (int count = shiftVal; count > ;)
  634. {
  635. if (count < shiftAmount)
  636. shiftAmount = count;
  637.  
  638. //Console.WriteLine("shiftAmount = {0}", shiftAmount);
  639.  
  640. ulong carry = ;
  641. for (int i = ; i < bufLen; i++)
  642. {
  643. ulong val = ((ulong)buffer[i]) << shiftAmount;
  644. val |= carry;
  645.  
  646. buffer[i] = (uint)(val & 0xFFFFFFFF);
  647. carry = val >> ;
  648. }
  649.  
  650. if (carry != )
  651. {
  652. if (bufLen + <= buffer.Length)
  653. {
  654. buffer[bufLen] = (uint)carry;
  655. bufLen++;
  656. }
  657. }
  658. count -= shiftAmount;
  659. }
  660. return bufLen;
  661. }
  662.  
  663. //***********************************************************************
  664. // Overloading of unary >> operators
  665. //***********************************************************************
  666.  
  667. public static BigInteger operator >>(BigInteger bi1, int shiftVal)
  668. {
  669. BigInteger result = new BigInteger(bi1);
  670. result.DataLength = shiftRight(result.data, shiftVal);
  671.  
  672. if ((bi1.data[maxLength - ] & 0x80000000) != ) // negative
  673. {
  674. for (int i = maxLength - ; i >= result.DataLength; i--)
  675. result.data[i] = 0xFFFFFFFF;
  676.  
  677. uint mask = 0x80000000;
  678. for (int i = ; i < ; i++)
  679. {
  680. if ((result.data[result.DataLength - ] & mask) != )
  681. break;
  682.  
  683. result.data[result.DataLength - ] |= mask;
  684. mask >>= ;
  685. }
  686. result.DataLength = maxLength;
  687. }
  688.  
  689. return result;
  690. }
  691.  
  692. private static int shiftRight(uint[] buffer, int shiftVal)
  693. {
  694. int shiftAmount = ;
  695. int invShift = ;
  696. int bufLen = buffer.Length;
  697.  
  698. while (bufLen > && buffer[bufLen - ] == )
  699. bufLen--;
  700.  
  701. //Console.WriteLine("bufLen = " + bufLen + " buffer.Length = " + buffer.Length);
  702.  
  703. for (int count = shiftVal; count > ;)
  704. {
  705. if (count < shiftAmount)
  706. {
  707. shiftAmount = count;
  708. invShift = - shiftAmount;
  709. }
  710.  
  711. //Console.WriteLine("shiftAmount = {0}", shiftAmount);
  712.  
  713. ulong carry = ;
  714. for (int i = bufLen - ; i >= ; i--)
  715. {
  716. ulong val = ((ulong)buffer[i]) >> shiftAmount;
  717. val |= carry;
  718.  
  719. carry = ((ulong)buffer[i]) << invShift;
  720. buffer[i] = (uint)(val);
  721. }
  722.  
  723. count -= shiftAmount;
  724. }
  725.  
  726. while (bufLen > && buffer[bufLen - ] == )
  727. bufLen--;
  728.  
  729. return bufLen;
  730. }
  731.  
  732. //***********************************************************************
  733. // Overloading of the NOT operator (1's complement)
  734. //***********************************************************************
  735.  
  736. public static BigInteger operator ~(BigInteger bi1)
  737. {
  738. BigInteger result = new BigInteger(bi1);
  739.  
  740. for (int i = ; i < maxLength; i++)
  741. result.data[i] = (uint)(~(bi1.data[i]));
  742.  
  743. result.DataLength = maxLength;
  744.  
  745. while (result.DataLength > && result.data[result.DataLength - ] == )
  746. result.DataLength--;
  747.  
  748. return result;
  749. }
  750.  
  751. //***********************************************************************
  752. // Overloading of the NEGATE operator (2's complement)
  753. //***********************************************************************
  754.  
  755. public static BigInteger operator -(BigInteger bi1)
  756. {
  757. // handle neg of zero separately since it'll cause an overflow
  758. // if we proceed.
  759.  
  760. if (bi1.DataLength == && bi1.data[] == )
  761. return (new BigInteger());
  762.  
  763. BigInteger result = new BigInteger(bi1);
  764.  
  765. // 1's complement
  766. for (int i = ; i < maxLength; i++)
  767. result.data[i] = (uint)(~(bi1.data[i]));
  768.  
  769. // add one to result of 1's complement
  770. long val, carry = ;
  771. int index = ;
  772.  
  773. while (carry != && index < maxLength)
  774. {
  775. val = (long)(result.data[index]);
  776. val++;
  777.  
  778. result.data[index] = (uint)(val & 0xFFFFFFFF);
  779. carry = val >> ;
  780.  
  781. index++;
  782. }
  783.  
  784. if ((bi1.data[maxLength - ] & 0x80000000) == (result.data[maxLength - ] & 0x80000000))
  785. throw (new ArithmeticException("Overflow in negation.\n"));
  786.  
  787. result.DataLength = maxLength;
  788.  
  789. while (result.DataLength > && result.data[result.DataLength - ] == )
  790. result.DataLength--;
  791. return result;
  792. }
  793.  
  794. //***********************************************************************
  795. // Overloading of equality operator
  796. //***********************************************************************
  797.  
  798. public static bool operator ==(BigInteger bi1, BigInteger bi2)
  799. {
  800. return bi1.Equals(bi2);
  801. }
  802.  
  803. public static bool operator !=(BigInteger bi1, BigInteger bi2)
  804. {
  805. return !(bi1.Equals(bi2));
  806. }
  807.  
  808. public override bool Equals(object o)
  809. {
  810. BigInteger bi = (BigInteger)o;
  811.  
  812. if (this.DataLength != bi.DataLength)
  813. return false;
  814.  
  815. for (int i = ; i < this.DataLength; i++)
  816. {
  817. if (this.data[i] != bi.data[i])
  818. return false;
  819. }
  820. return true;
  821. }
  822.  
  823. public override int GetHashCode()
  824. {
  825. return this.ToString().GetHashCode();
  826. }
  827.  
  828. //***********************************************************************
  829. // Overloading of inequality operator
  830. //***********************************************************************
  831.  
  832. public static bool operator >(BigInteger bi1, BigInteger bi2)
  833. {
  834. int pos = maxLength - ;
  835.  
  836. // bi1 is negative, bi2 is positive
  837. if ((bi1.data[pos] & 0x80000000) != && (bi2.data[pos] & 0x80000000) == )
  838. return false;
  839.  
  840. // bi1 is positive, bi2 is negative
  841. else if ((bi1.data[pos] & 0x80000000) == && (bi2.data[pos] & 0x80000000) != )
  842. return true;
  843.  
  844. // same sign
  845. int len = (bi1.DataLength > bi2.DataLength) ? bi1.DataLength : bi2.DataLength;
  846. for (pos = len - ; pos >= && bi1.data[pos] == bi2.data[pos]; pos--) ;
  847.  
  848. if (pos >= )
  849. {
  850. if (bi1.data[pos] > bi2.data[pos])
  851. return true;
  852. return false;
  853. }
  854. return false;
  855. }
  856.  
  857. public static bool operator <(BigInteger bi1, BigInteger bi2)
  858. {
  859. int pos = maxLength - ;
  860.  
  861. // bi1 is negative, bi2 is positive
  862. if ((bi1.data[pos] & 0x80000000) != && (bi2.data[pos] & 0x80000000) == )
  863. return true;
  864.  
  865. // bi1 is positive, bi2 is negative
  866. else if ((bi1.data[pos] & 0x80000000) == && (bi2.data[pos] & 0x80000000) != )
  867. return false;
  868.  
  869. // same sign
  870. int len = (bi1.DataLength > bi2.DataLength) ? bi1.DataLength : bi2.DataLength;
  871. for (pos = len - ; pos >= && bi1.data[pos] == bi2.data[pos]; pos--) ;
  872.  
  873. if (pos >= )
  874. {
  875. if (bi1.data[pos] < bi2.data[pos])
  876. return true;
  877. return false;
  878. }
  879. return false;
  880. }
  881.  
  882. public static bool operator >=(BigInteger bi1, BigInteger bi2)
  883. {
  884. return (bi1 == bi2 || bi1 > bi2);
  885. }
  886.  
  887. public static bool operator <=(BigInteger bi1, BigInteger bi2)
  888. {
  889. return (bi1 == bi2 || bi1 < bi2);
  890. }
  891.  
  892. //***********************************************************************
  893. // Private function that supports the division of two numbers with
  894. // a divisor that has more than 1 digit.
  895. //
  896. // Algorithm taken from [1]
  897. //***********************************************************************
  898.  
  899. private static void multiByteDivide(BigInteger bi1, BigInteger bi2,
  900. BigInteger outQuotient, BigInteger outRemainder)
  901. {
  902. uint[] result = new uint[maxLength];
  903.  
  904. int remainderLen = bi1.DataLength + ;
  905. uint[] remainder = new uint[remainderLen];
  906.  
  907. uint mask = 0x80000000;
  908. uint val = bi2.data[bi2.DataLength - ];
  909. int shift = , resultPos = ;
  910.  
  911. while (mask != && (val & mask) == )
  912. {
  913. shift++; mask >>= ;
  914. }
  915.  
  916. //Console.WriteLine("shift = {0}", shift);
  917. //Console.WriteLine("Before bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);
  918.  
  919. for (int i = ; i < bi1.DataLength; i++)
  920. remainder[i] = bi1.data[i];
  921. shiftLeft(remainder, shift);
  922. bi2 = bi2 << shift;
  923.  
  924. /*
  925. Console.WriteLine("bi1 Len = {0}, bi2 Len = {1}", bi1.dataLength, bi2.dataLength);
  926. Console.WriteLine("dividend = " + bi1 + "\ndivisor = " + bi2);
  927. for(int q = remainderLen - 1; q >= 0; q--)
  928. Console.Write("{0:x2}", remainder[q]);
  929. Console.WriteLine();
  930. */
  931.  
  932. int j = remainderLen - bi2.DataLength;
  933. int pos = remainderLen - ;
  934.  
  935. ulong firstDivisorByte = bi2.data[bi2.DataLength - ];
  936. ulong secondDivisorByte = bi2.data[bi2.DataLength - ];
  937.  
  938. int divisorLen = bi2.DataLength + ;
  939. uint[] dividendPart = new uint[divisorLen];
  940.  
  941. while (j > )
  942. {
  943. ulong dividend = ((ulong)remainder[pos] << ) + (ulong)remainder[pos - ];
  944. //Console.WriteLine("dividend = {0}", dividend);
  945.  
  946. ulong q_hat = dividend / firstDivisorByte;
  947. ulong r_hat = dividend % firstDivisorByte;
  948.  
  949. //Console.WriteLine("q_hat = {0:X}, r_hat = {1:X}", q_hat, r_hat);
  950.  
  951. bool done = false;
  952. while (!done)
  953. {
  954. done = true;
  955.  
  956. if (q_hat == 0x100000000 ||
  957. (q_hat * secondDivisorByte) > ((r_hat << ) + remainder[pos - ]))
  958. {
  959. q_hat--;
  960. r_hat += firstDivisorByte;
  961.  
  962. if (r_hat < 0x100000000)
  963. done = false;
  964. }
  965. }
  966.  
  967. for (int h = ; h < divisorLen; h++)
  968. dividendPart[h] = remainder[pos - h];
  969.  
  970. BigInteger kk = new BigInteger(dividendPart);
  971. BigInteger ss = bi2 * (long)q_hat;
  972.  
  973. //Console.WriteLine("ss before = " + ss);
  974. while (ss > kk)
  975. {
  976. q_hat--;
  977. ss -= bi2;
  978. //Console.WriteLine(ss);
  979. }
  980. BigInteger yy = kk - ss;
  981.  
  982. //Console.WriteLine("ss = " + ss);
  983. //Console.WriteLine("kk = " + kk);
  984. //Console.WriteLine("yy = " + yy);
  985.  
  986. for (int h = ; h < divisorLen; h++)
  987. remainder[pos - h] = yy.data[bi2.DataLength - h];
  988.  
  989. /*
  990. Console.WriteLine("dividend = ");
  991. for(int q = remainderLen - 1; q >= 0; q--)
  992. Console.Write("{0:x2}", remainder[q]);
  993. Console.WriteLine("\n************ q_hat = {0:X}\n", q_hat);
  994. */
  995.  
  996. result[resultPos++] = (uint)q_hat;
  997.  
  998. pos--;
  999. j--;
  1000. }
  1001.  
  1002. outQuotient.DataLength = resultPos;
  1003. int y = ;
  1004. for (int x = outQuotient.DataLength - ; x >= ; x--, y++)
  1005. outQuotient.data[y] = result[x];
  1006. for (; y < maxLength; y++)
  1007. outQuotient.data[y] = ;
  1008.  
  1009. while (outQuotient.DataLength > && outQuotient.data[outQuotient.DataLength - ] == )
  1010. outQuotient.DataLength--;
  1011.  
  1012. if (outQuotient.DataLength == )
  1013. outQuotient.DataLength = ;
  1014.  
  1015. outRemainder.DataLength = shiftRight(remainder, shift);
  1016.  
  1017. for (y = ; y < outRemainder.DataLength; y++)
  1018. outRemainder.data[y] = remainder[y];
  1019. for (; y < maxLength; y++)
  1020. outRemainder.data[y] = ;
  1021. }
  1022.  
  1023. //***********************************************************************
  1024. // Private function that supports the division of two numbers with
  1025. // a divisor that has only 1 digit.
  1026. //***********************************************************************
  1027.  
  1028. private static void singleByteDivide(BigInteger bi1, BigInteger bi2,
  1029. BigInteger outQuotient, BigInteger outRemainder)
  1030. {
  1031. uint[] result = new uint[maxLength];
  1032. int resultPos = ;
  1033.  
  1034. // copy dividend to reminder
  1035. for (int i = ; i < maxLength; i++)
  1036. outRemainder.data[i] = bi1.data[i];
  1037. outRemainder.DataLength = bi1.DataLength;
  1038.  
  1039. while (outRemainder.DataLength > && outRemainder.data[outRemainder.DataLength - ] == )
  1040. outRemainder.DataLength--;
  1041.  
  1042. ulong divisor = (ulong)bi2.data[];
  1043. int pos = outRemainder.DataLength - ;
  1044. ulong dividend = (ulong)outRemainder.data[pos];
  1045.  
  1046. //Console.WriteLine("divisor = " + divisor + " dividend = " + dividend);
  1047. //Console.WriteLine("divisor = " + bi2 + "\ndividend = " + bi1);
  1048.  
  1049. if (dividend >= divisor)
  1050. {
  1051. ulong quotient = dividend / divisor;
  1052. result[resultPos++] = (uint)quotient;
  1053.  
  1054. outRemainder.data[pos] = (uint)(dividend % divisor);
  1055. }
  1056. pos--;
  1057.  
  1058. while (pos >= )
  1059. {
  1060. //Console.WriteLine(pos);
  1061.  
  1062. dividend = ((ulong)outRemainder.data[pos + ] << ) + (ulong)outRemainder.data[pos];
  1063. ulong quotient = dividend / divisor;
  1064. result[resultPos++] = (uint)quotient;
  1065.  
  1066. outRemainder.data[pos + ] = ;
  1067. outRemainder.data[pos--] = (uint)(dividend % divisor);
  1068. //Console.WriteLine(">>>> " + bi1);
  1069. }
  1070.  
  1071. outQuotient.DataLength = resultPos;
  1072. int j = ;
  1073. for (int i = outQuotient.DataLength - ; i >= ; i--, j++)
  1074. outQuotient.data[j] = result[i];
  1075. for (; j < maxLength; j++)
  1076. outQuotient.data[j] = ;
  1077.  
  1078. while (outQuotient.DataLength > && outQuotient.data[outQuotient.DataLength - ] == )
  1079. outQuotient.DataLength--;
  1080.  
  1081. if (outQuotient.DataLength == )
  1082. outQuotient.DataLength = ;
  1083.  
  1084. while (outRemainder.DataLength > && outRemainder.data[outRemainder.DataLength - ] == )
  1085. outRemainder.DataLength--;
  1086. }
  1087.  
  1088. //***********************************************************************
  1089. // Overloading of division operator
  1090. //***********************************************************************
  1091.  
  1092. public static BigInteger operator /(BigInteger bi1, BigInteger bi2)
  1093. {
  1094. BigInteger quotient = new BigInteger();
  1095. BigInteger remainder = new BigInteger();
  1096.  
  1097. int lastPos = maxLength - ;
  1098. bool divisorNeg = false, dividendNeg = false;
  1099.  
  1100. if ((bi1.data[lastPos] & 0x80000000) != ) // bi1 negative
  1101. {
  1102. bi1 = -bi1;
  1103. dividendNeg = true;
  1104. }
  1105. if ((bi2.data[lastPos] & 0x80000000) != ) // bi2 negative
  1106. {
  1107. bi2 = -bi2;
  1108. divisorNeg = true;
  1109. }
  1110.  
  1111. if (bi1 < bi2)
  1112. {
  1113. return quotient;
  1114. }
  1115.  
  1116. else
  1117. {
  1118. if (bi2.DataLength == )
  1119. singleByteDivide(bi1, bi2, quotient, remainder);
  1120. else
  1121. multiByteDivide(bi1, bi2, quotient, remainder);
  1122.  
  1123. if (dividendNeg != divisorNeg)
  1124. return -quotient;
  1125.  
  1126. return quotient;
  1127. }
  1128. }
  1129.  
  1130. //***********************************************************************
  1131. // Overloading of modulus operator
  1132. //***********************************************************************
  1133.  
  1134. public static BigInteger operator %(BigInteger bi1, BigInteger bi2)
  1135. {
  1136. BigInteger quotient = new BigInteger();
  1137. BigInteger remainder = new BigInteger(bi1);
  1138.  
  1139. int lastPos = maxLength - ;
  1140. bool dividendNeg = false;
  1141.  
  1142. if ((bi1.data[lastPos] & 0x80000000) != ) // bi1 negative
  1143. {
  1144. bi1 = -bi1;
  1145. dividendNeg = true;
  1146. }
  1147. if ((bi2.data[lastPos] & 0x80000000) != ) // bi2 negative
  1148. bi2 = -bi2;
  1149.  
  1150. if (bi1 < bi2)
  1151. {
  1152. return remainder;
  1153. }
  1154.  
  1155. else
  1156. {
  1157. if (bi2.DataLength == )
  1158. singleByteDivide(bi1, bi2, quotient, remainder);
  1159. else
  1160. multiByteDivide(bi1, bi2, quotient, remainder);
  1161.  
  1162. if (dividendNeg)
  1163. return -remainder;
  1164.  
  1165. return remainder;
  1166. }
  1167. }
  1168.  
  1169. //***********************************************************************
  1170. // Overloading of bitwise AND operator
  1171. //***********************************************************************
  1172.  
  1173. public static BigInteger operator &(BigInteger bi1, BigInteger bi2)
  1174. {
  1175. BigInteger result = new BigInteger();
  1176.  
  1177. int len = (bi1.DataLength > bi2.DataLength) ? bi1.DataLength : bi2.DataLength;
  1178.  
  1179. for (int i = ; i < len; i++)
  1180. {
  1181. uint sum = (uint)(bi1.data[i] & bi2.data[i]);
  1182. result.data[i] = sum;
  1183. }
  1184.  
  1185. result.DataLength = maxLength;
  1186.  
  1187. while (result.DataLength > && result.data[result.DataLength - ] == )
  1188. result.DataLength--;
  1189.  
  1190. return result;
  1191. }
  1192.  
  1193. //***********************************************************************
  1194. // Overloading of bitwise OR operator
  1195. //***********************************************************************
  1196.  
  1197. public static BigInteger operator |(BigInteger bi1, BigInteger bi2)
  1198. {
  1199. BigInteger result = new BigInteger();
  1200.  
  1201. int len = (bi1.DataLength > bi2.DataLength) ? bi1.DataLength : bi2.DataLength;
  1202.  
  1203. for (int i = ; i < len; i++)
  1204. {
  1205. uint sum = (uint)(bi1.data[i] | bi2.data[i]);
  1206. result.data[i] = sum;
  1207. }
  1208.  
  1209. result.DataLength = maxLength;
  1210.  
  1211. while (result.DataLength > && result.data[result.DataLength - ] == )
  1212. result.DataLength--;
  1213.  
  1214. return result;
  1215. }
  1216.  
  1217. //***********************************************************************
  1218. // Overloading of bitwise XOR operator
  1219. //***********************************************************************
  1220.  
  1221. public static BigInteger operator ^(BigInteger bi1, BigInteger bi2)
  1222. {
  1223. BigInteger result = new BigInteger();
  1224.  
  1225. int len = (bi1.DataLength > bi2.DataLength) ? bi1.DataLength : bi2.DataLength;
  1226.  
  1227. for (int i = ; i < len; i++)
  1228. {
  1229. uint sum = (uint)(bi1.data[i] ^ bi2.data[i]);
  1230. result.data[i] = sum;
  1231. }
  1232.  
  1233. result.DataLength = maxLength;
  1234.  
  1235. while (result.DataLength > && result.data[result.DataLength - ] == )
  1236. result.DataLength--;
  1237.  
  1238. return result;
  1239. }
  1240.  
  1241. //***********************************************************************
  1242. // Returns max(this, bi)
  1243. //***********************************************************************
  1244.  
  1245. public BigInteger max(BigInteger bi)
  1246. {
  1247. if (this > bi)
  1248. return (new BigInteger(this));
  1249. else
  1250. return (new BigInteger(bi));
  1251. }
  1252.  
  1253. //***********************************************************************
  1254. // Returns min(this, bi)
  1255. //***********************************************************************
  1256.  
  1257. public BigInteger min(BigInteger bi)
  1258. {
  1259. if (this < bi)
  1260. return (new BigInteger(this));
  1261. else
  1262. return (new BigInteger(bi));
  1263.  
  1264. }
  1265.  
  1266. //***********************************************************************
  1267. // Returns the absolute value
  1268. //***********************************************************************
  1269.  
  1270. public BigInteger abs()
  1271. {
  1272. if ((this.data[maxLength - ] & 0x80000000) != )
  1273. return (-this);
  1274. else
  1275. return (new BigInteger(this));
  1276. }
  1277.  
  1278. //***********************************************************************
  1279. // Returns a string representing the BigInteger in base 10.
  1280. //***********************************************************************
  1281.  
  1282. public override string ToString()
  1283. {
  1284. return ToString();
  1285. }
  1286.  
  1287. //***********************************************************************
  1288. // Returns a string representing the BigInteger in sign-and-magnitude
  1289. // format in the specified radix.
  1290. //
  1291. // Example
  1292. // -------
  1293. // If the value of BigInteger is -255 in base 10, then
  1294. // ToString(16) returns "-FF"
  1295. //
  1296. //***********************************************************************
  1297.  
  1298. public string ToString(int radix)
  1299. {
  1300. if (radix < || radix > )
  1301. throw (new ArgumentException("Radix must be >= 2 and <= 36"));
  1302.  
  1303. string charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1304. string result = "";
  1305.  
  1306. BigInteger a = this;
  1307.  
  1308. bool negative = false;
  1309. if ((a.data[maxLength - ] & 0x80000000) != )
  1310. {
  1311. negative = true;
  1312. try
  1313. {
  1314. a = -a;
  1315. }
  1316. catch (Exception) { }
  1317. }
  1318.  
  1319. BigInteger quotient = new BigInteger();
  1320. BigInteger remainder = new BigInteger();
  1321. BigInteger biRadix = new BigInteger(radix);
  1322.  
  1323. if (a.DataLength == && a.data[] == )
  1324. result = "";
  1325. else
  1326. {
  1327. while (a.DataLength > || (a.DataLength == && a.data[] != ))
  1328. {
  1329. singleByteDivide(a, biRadix, quotient, remainder);
  1330.  
  1331. if (remainder.data[] < )
  1332. result = remainder.data[] + result;
  1333. else
  1334. result = charSet[(int)remainder.data[] - ] + result;
  1335.  
  1336. a = quotient;
  1337. }
  1338. if (negative)
  1339. result = "-" + result;
  1340. }
  1341.  
  1342. return result;
  1343. }
  1344.  
  1345. //***********************************************************************
  1346. // Returns a hex string showing the contains of the BigInteger
  1347. //
  1348. // Examples
  1349. // -------
  1350. // 1) If the value of BigInteger is 255 in base 10, then
  1351. // ToHexString() returns "FF"
  1352. //
  1353. // 2) If the value of BigInteger is -255 in base 10, then
  1354. // ToHexString() returns ".....FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01",
  1355. // which is the 2's complement representation of -255.
  1356. //
  1357. //***********************************************************************
  1358.  
  1359. public string ToHexString()
  1360. {
  1361. string result = data[DataLength - ].ToString("X");
  1362.  
  1363. for (int i = DataLength - ; i >= ; i--)
  1364. {
  1365. result += data[i].ToString("X8");
  1366. }
  1367.  
  1368. return result;
  1369. }
  1370.  
  1371. //***********************************************************************
  1372. // Modulo Exponentiation
  1373. //***********************************************************************
  1374.  
  1375. public BigInteger modPow(BigInteger exp, BigInteger n)
  1376. {
  1377. if ((exp.data[maxLength - ] & 0x80000000) != )
  1378. throw (new ArithmeticException("Positive exponents only."));
  1379.  
  1380. BigInteger resultNum = ;
  1381. BigInteger tempNum;
  1382. bool thisNegative = false;
  1383.  
  1384. if ((this.data[maxLength - ] & 0x80000000) != ) // negative this
  1385. {
  1386. tempNum = -this % n;
  1387. thisNegative = true;
  1388. }
  1389. else
  1390. tempNum = this % n; // ensures (tempNum * tempNum) < b^(2k)
  1391.  
  1392. if ((n.data[maxLength - ] & 0x80000000) != ) // negative n
  1393. n = -n;
  1394.  
  1395. // calculate constant = b^(2k) / m
  1396. BigInteger constant = new BigInteger();
  1397.  
  1398. int i = n.DataLength << ;
  1399. constant.data[i] = 0x00000001;
  1400. constant.DataLength = i + ;
  1401.  
  1402. constant = constant / n;
  1403. int totalBits = exp.bitCount();
  1404. int count = ;
  1405.  
  1406. // perform squaring and multiply exponentiation
  1407. for (int pos = ; pos < exp.DataLength; pos++)
  1408. {
  1409. uint mask = 0x01;
  1410. //Console.WriteLine("pos = " + pos);
  1411.  
  1412. for (int index = ; index < ; index++)
  1413. {
  1414. if ((exp.data[pos] & mask) != )
  1415. resultNum = BarrettReduction(resultNum * tempNum, n, constant);
  1416.  
  1417. mask <<= ;
  1418.  
  1419. tempNum = BarrettReduction(tempNum * tempNum, n, constant);
  1420.  
  1421. if (tempNum.DataLength == && tempNum.data[] == )
  1422. {
  1423. if (thisNegative && (exp.data[] & 0x1) != ) //odd exp
  1424. return -resultNum;
  1425. return resultNum;
  1426. }
  1427. count++;
  1428. if (count == totalBits)
  1429. break;
  1430. }
  1431. }
  1432.  
  1433. if (thisNegative && (exp.data[] & 0x1) != ) //odd exp
  1434. return -resultNum;
  1435.  
  1436. return resultNum;
  1437. }
  1438.  
  1439. //***********************************************************************
  1440. // Fast calculation of modular reduction using Barrett's reduction.
  1441. // Requires x < b^(2k), where b is the base. In this case, base is
  1442. // 2^32 (uint).
  1443. //
  1444. // Reference [4]
  1445. //***********************************************************************
  1446.  
  1447. private BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant)
  1448. {
  1449. int k = n.DataLength,
  1450. kPlusOne = k + ,
  1451. kMinusOne = k - ;
  1452.  
  1453. BigInteger q1 = new BigInteger();
  1454.  
  1455. // q1 = x / b^(k-1)
  1456. for (int i = kMinusOne, j = ; i < x.DataLength; i++, j++)
  1457. q1.data[j] = x.data[i];
  1458. q1.DataLength = x.DataLength - kMinusOne;
  1459. if (q1.DataLength <= )
  1460. q1.DataLength = ;
  1461.  
  1462. BigInteger q2 = q1 * constant;
  1463. BigInteger q3 = new BigInteger();
  1464.  
  1465. // q3 = q2 / b^(k+1)
  1466. for (int i = kPlusOne, j = ; i < q2.DataLength; i++, j++)
  1467. q3.data[j] = q2.data[i];
  1468. q3.DataLength = q2.DataLength - kPlusOne;
  1469. if (q3.DataLength <= )
  1470. q3.DataLength = ;
  1471.  
  1472. // r1 = x mod b^(k+1)
  1473. // i.e. keep the lowest (k+1) words
  1474. BigInteger r1 = new BigInteger();
  1475. int lengthToCopy = (x.DataLength > kPlusOne) ? kPlusOne : x.DataLength;
  1476. for (int i = ; i < lengthToCopy; i++)
  1477. r1.data[i] = x.data[i];
  1478. r1.DataLength = lengthToCopy;
  1479.  
  1480. // r2 = (q3 * n) mod b^(k+1)
  1481. // partial multiplication of q3 and n
  1482.  
  1483. BigInteger r2 = new BigInteger();
  1484. for (int i = ; i < q3.DataLength; i++)
  1485. {
  1486. if (q3.data[i] == ) continue;
  1487.  
  1488. ulong mcarry = ;
  1489. int t = i;
  1490. for (int j = ; j < n.DataLength && t < kPlusOne; j++, t++)
  1491. {
  1492. // t = i + j
  1493. ulong val = ((ulong)q3.data[i] * (ulong)n.data[j]) +
  1494. (ulong)r2.data[t] + mcarry;
  1495.  
  1496. r2.data[t] = (uint)(val & 0xFFFFFFFF);
  1497. mcarry = (val >> );
  1498. }
  1499.  
  1500. if (t < kPlusOne)
  1501. r2.data[t] = (uint)mcarry;
  1502. }
  1503. r2.DataLength = kPlusOne;
  1504. while (r2.DataLength > && r2.data[r2.DataLength - ] == )
  1505. r2.DataLength--;
  1506.  
  1507. r1 -= r2;
  1508. if ((r1.data[maxLength - ] & 0x80000000) != ) // negative
  1509. {
  1510. BigInteger val = new BigInteger();
  1511. val.data[kPlusOne] = 0x00000001;
  1512. val.DataLength = kPlusOne + ;
  1513. r1 += val;
  1514. }
  1515.  
  1516. while (r1 >= n)
  1517. r1 -= n;
  1518.  
  1519. return r1;
  1520. }
  1521.  
  1522. //***********************************************************************
  1523. // Returns gcd(this, bi)
  1524. //***********************************************************************
  1525.  
  1526. public BigInteger gcd(BigInteger bi)
  1527. {
  1528. BigInteger x;
  1529. BigInteger y;
  1530.  
  1531. if ((data[maxLength - ] & 0x80000000) != ) // negative
  1532. x = -this;
  1533. else
  1534. x = this;
  1535.  
  1536. if ((bi.data[maxLength - ] & 0x80000000) != ) // negative
  1537. y = -bi;
  1538. else
  1539. y = bi;
  1540.  
  1541. BigInteger g = y;
  1542.  
  1543. while (x.DataLength > || (x.DataLength == && x.data[] != ))
  1544. {
  1545. g = x;
  1546. x = y % x;
  1547. y = g;
  1548. }
  1549.  
  1550. return g;
  1551. }
  1552.  
  1553. //***********************************************************************
  1554. // Populates "this" with the specified amount of random bits
  1555. //***********************************************************************
  1556.  
  1557. public void genRandomBits(int bits, Random rand)
  1558. {
  1559. int dwords = bits >> ;
  1560. int remBits = bits & 0x1F;
  1561.  
  1562. if (remBits != )
  1563. dwords++;
  1564.  
  1565. if (dwords > maxLength)
  1566. throw (new ArithmeticException("Number of required bits > maxLength."));
  1567.  
  1568. for (int i = ; i < dwords; i++)
  1569. data[i] = (uint)(rand.NextDouble() * 0x100000000);
  1570.  
  1571. for (int i = dwords; i < maxLength; i++)
  1572. data[i] = ;
  1573.  
  1574. if (remBits != )
  1575. {
  1576. uint mask = (uint)(0x01 << (remBits - ));
  1577. data[dwords - ] |= mask;
  1578.  
  1579. mask = (uint)(0xFFFFFFFF >> ( - remBits));
  1580. data[dwords - ] &= mask;
  1581. }
  1582. else
  1583. data[dwords - ] |= 0x80000000;
  1584.  
  1585. DataLength = dwords;
  1586.  
  1587. if (DataLength == )
  1588. DataLength = ;
  1589. }
  1590.  
  1591. //***********************************************************************
  1592. // Returns the position of the most significant bit in the BigInteger.
  1593. //
  1594. // Eg. The result is 0, if the value of BigInteger is 0...0000 0000
  1595. // The result is 1, if the value of BigInteger is 0...0000 0001
  1596. // The result is 2, if the value of BigInteger is 0...0000 0010
  1597. // The result is 2, if the value of BigInteger is 0...0000 0011
  1598. //
  1599. //***********************************************************************
  1600.  
  1601. public int bitCount()
  1602. {
  1603. while (DataLength > && data[DataLength - ] == )
  1604. DataLength--;
  1605.  
  1606. uint value = data[DataLength - ];
  1607. uint mask = 0x80000000;
  1608. int bits = ;
  1609.  
  1610. while (bits > && (value & mask) == )
  1611. {
  1612. bits--;
  1613. mask >>= ;
  1614. }
  1615. bits += ((DataLength - ) << );
  1616.  
  1617. return bits;
  1618. }
  1619.  
  1620. //***********************************************************************
  1621. // Probabilistic prime test based on Fermat's little theorem
  1622. //
  1623. // for any a < p (p does not divide a) if
  1624. // a^(p-1) mod p != 1 then p is not prime.
  1625. //
  1626. // Otherwise, p is probably prime (pseudoprime to the chosen base).
  1627. //
  1628. // Returns
  1629. // -------
  1630. // True if "this" is a pseudoprime to randomly chosen
  1631. // bases. The number of chosen bases is given by the "confidence"
  1632. // parameter.
  1633. //
  1634. // False if "this" is definitely NOT prime.
  1635. //
  1636. // Note - this method is fast but fails for Carmichael numbers except
  1637. // when the randomly chosen base is a factor of the number.
  1638. //
  1639. //***********************************************************************
  1640.  
  1641. public bool FermatLittleTest(int confidence)
  1642. {
  1643. BigInteger thisVal;
  1644. if ((this.data[maxLength - ] & 0x80000000) != ) // negative
  1645. thisVal = -this;
  1646. else
  1647. thisVal = this;
  1648.  
  1649. if (thisVal.DataLength == )
  1650. {
  1651. // test small numbers
  1652. if (thisVal.data[] == || thisVal.data[] == )
  1653. return false;
  1654. else if (thisVal.data[] == || thisVal.data[] == )
  1655. return true;
  1656. }
  1657.  
  1658. if ((thisVal.data[] & 0x1) == ) // even numbers
  1659. return false;
  1660.  
  1661. int bits = thisVal.bitCount();
  1662. BigInteger a = new BigInteger();
  1663. BigInteger p_sub1 = thisVal - (new BigInteger());
  1664. Random rand = new Random();
  1665.  
  1666. for (int round = ; round < confidence; round++)
  1667. {
  1668. bool done = false;
  1669.  
  1670. while (!done) // generate a < n
  1671. {
  1672. int testBits = ;
  1673.  
  1674. // make sure "a" has at least 2 bits
  1675. while (testBits < )
  1676. testBits = (int)(rand.NextDouble() * bits);
  1677.  
  1678. a.genRandomBits(testBits, rand);
  1679.  
  1680. int byteLen = a.DataLength;
  1681.  
  1682. // make sure "a" is not 0
  1683. if (byteLen > || (byteLen == && a.data[] != ))
  1684. done = true;
  1685. }
  1686.  
  1687. // check whether a factor exists (fix for version 1.03)
  1688. BigInteger gcdTest = a.gcd(thisVal);
  1689. if (gcdTest.DataLength == && gcdTest.data[] != )
  1690. return false;
  1691.  
  1692. // calculate a^(p-1) mod p
  1693. BigInteger expResult = a.modPow(p_sub1, thisVal);
  1694.  
  1695. int resultLen = expResult.DataLength;
  1696.  
  1697. // is NOT prime is a^(p-1) mod p != 1
  1698.  
  1699. if (resultLen > || (resultLen == && expResult.data[] != ))
  1700. {
  1701. //Console.WriteLine("a = " + a.ToString());
  1702. return false;
  1703. }
  1704. }
  1705.  
  1706. return true;
  1707. }
  1708.  
  1709. //***********************************************************************
  1710. // Probabilistic prime test based on Rabin-Miller's
  1711. //
  1712. // for any p > 0 with p - 1 = 2^s * t
  1713. //
  1714. // p is probably prime (strong pseudoprime) if for any a < p,
  1715. // 1) a^t mod p = 1 or
  1716. // 2) a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
  1717. //
  1718. // Otherwise, p is composite.
  1719. //
  1720. // Returns
  1721. // -------
  1722. // True if "this" is a strong pseudoprime to randomly chosen
  1723. // bases. The number of chosen bases is given by the "confidence"
  1724. // parameter.
  1725. //
  1726. // False if "this" is definitely NOT prime.
  1727. //
  1728. //***********************************************************************
  1729.  
  1730. public bool RabinMillerTest(int confidence)
  1731. {
  1732. BigInteger thisVal;
  1733. if ((this.data[maxLength - ] & 0x80000000) != ) // negative
  1734. thisVal = -this;
  1735. else
  1736. thisVal = this;
  1737.  
  1738. if (thisVal.DataLength == )
  1739. {
  1740. // test small numbers
  1741. if (thisVal.data[] == || thisVal.data[] == )
  1742. return false;
  1743. else if (thisVal.data[] == || thisVal.data[] == )
  1744. return true;
  1745. }
  1746.  
  1747. if ((thisVal.data[] & 0x1) == ) // even numbers
  1748. return false;
  1749.  
  1750. // calculate values of s and t
  1751. BigInteger p_sub1 = thisVal - (new BigInteger());
  1752. int s = ;
  1753.  
  1754. for (int index = ; index < p_sub1.DataLength; index++)
  1755. {
  1756. uint mask = 0x01;
  1757.  
  1758. for (int i = ; i < ; i++)
  1759. {
  1760. if ((p_sub1.data[index] & mask) != )
  1761. {
  1762. index = p_sub1.DataLength; // to break the outer loop
  1763. break;
  1764. }
  1765. mask <<= ;
  1766. s++;
  1767. }
  1768. }
  1769.  
  1770. BigInteger t = p_sub1 >> s;
  1771.  
  1772. int bits = thisVal.bitCount();
  1773. BigInteger a = new BigInteger();
  1774. Random rand = new Random();
  1775.  
  1776. for (int round = ; round < confidence; round++)
  1777. {
  1778. bool done = false;
  1779.  
  1780. while (!done) // generate a < n
  1781. {
  1782. int testBits = ;
  1783.  
  1784. // make sure "a" has at least 2 bits
  1785. while (testBits < )
  1786. testBits = (int)(rand.NextDouble() * bits);
  1787.  
  1788. a.genRandomBits(testBits, rand);
  1789.  
  1790. int byteLen = a.DataLength;
  1791.  
  1792. // make sure "a" is not 0
  1793. if (byteLen > || (byteLen == && a.data[] != ))
  1794. done = true;
  1795. }
  1796.  
  1797. // check whether a factor exists (fix for version 1.03)
  1798. BigInteger gcdTest = a.gcd(thisVal);
  1799. if (gcdTest.DataLength == && gcdTest.data[] != )
  1800. return false;
  1801.  
  1802. BigInteger b = a.modPow(t, thisVal);
  1803.  
  1804. /*
  1805. Console.WriteLine("a = " + a.ToString(10));
  1806. Console.WriteLine("b = " + b.ToString(10));
  1807. Console.WriteLine("t = " + t.ToString(10));
  1808. Console.WriteLine("s = " + s);
  1809. */
  1810.  
  1811. bool result = false;
  1812.  
  1813. if (b.DataLength == && b.data[] == ) // a^t mod p = 1
  1814. result = true;
  1815.  
  1816. for (int j = ; result == false && j < s; j++)
  1817. {
  1818. if (b == p_sub1) // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
  1819. {
  1820. result = true;
  1821. break;
  1822. }
  1823.  
  1824. b = (b * b) % thisVal;
  1825. }
  1826.  
  1827. if (result == false)
  1828. return false;
  1829. }
  1830. return true;
  1831. }
  1832.  
  1833. //***********************************************************************
  1834. // Probabilistic prime test based on Solovay-Strassen (Euler Criterion)
  1835. //
  1836. // p is probably prime if for any a < p (a is not multiple of p),
  1837. // a^((p-1)/2) mod p = J(a, p)
  1838. //
  1839. // where J is the Jacobi symbol.
  1840. //
  1841. // Otherwise, p is composite.
  1842. //
  1843. // Returns
  1844. // -------
  1845. // True if "this" is a Euler pseudoprime to randomly chosen
  1846. // bases. The number of chosen bases is given by the "confidence"
  1847. // parameter.
  1848. //
  1849. // False if "this" is definitely NOT prime.
  1850. //
  1851. //***********************************************************************
  1852.  
  1853. public bool SolovayStrassenTest(int confidence)
  1854. {
  1855. BigInteger thisVal;
  1856. if ((this.data[maxLength - ] & 0x80000000) != ) // negative
  1857. thisVal = -this;
  1858. else
  1859. thisVal = this;
  1860.  
  1861. if (thisVal.DataLength == )
  1862. {
  1863. // test small numbers
  1864. if (thisVal.data[] == || thisVal.data[] == )
  1865. return false;
  1866. else if (thisVal.data[] == || thisVal.data[] == )
  1867. return true;
  1868. }
  1869.  
  1870. if ((thisVal.data[] & 0x1) == ) // even numbers
  1871. return false;
  1872.  
  1873. int bits = thisVal.bitCount();
  1874. BigInteger a = new BigInteger();
  1875. BigInteger p_sub1 = thisVal - ;
  1876. BigInteger p_sub1_shift = p_sub1 >> ;
  1877.  
  1878. Random rand = new Random();
  1879.  
  1880. for (int round = ; round < confidence; round++)
  1881. {
  1882. bool done = false;
  1883.  
  1884. while (!done) // generate a < n
  1885. {
  1886. int testBits = ;
  1887.  
  1888. // make sure "a" has at least 2 bits
  1889. while (testBits < )
  1890. testBits = (int)(rand.NextDouble() * bits);
  1891.  
  1892. a.genRandomBits(testBits, rand);
  1893.  
  1894. int byteLen = a.DataLength;
  1895.  
  1896. // make sure "a" is not 0
  1897. if (byteLen > || (byteLen == && a.data[] != ))
  1898. done = true;
  1899. }
  1900.  
  1901. // check whether a factor exists (fix for version 1.03)
  1902. BigInteger gcdTest = a.gcd(thisVal);
  1903. if (gcdTest.DataLength == && gcdTest.data[] != )
  1904. return false;
  1905.  
  1906. // calculate a^((p-1)/2) mod p
  1907.  
  1908. BigInteger expResult = a.modPow(p_sub1_shift, thisVal);
  1909. if (expResult == p_sub1)
  1910. expResult = -;
  1911.  
  1912. // calculate Jacobi symbol
  1913. BigInteger jacob = Jacobi(a, thisVal);
  1914.  
  1915. //Console.WriteLine("a = " + a.ToString(10) + " b = " + thisVal.ToString(10));
  1916. //Console.WriteLine("expResult = " + expResult.ToString(10) + " Jacob = " + jacob.ToString(10));
  1917.  
  1918. // if they are different then it is not prime
  1919. if (expResult != jacob)
  1920. return false;
  1921. }
  1922.  
  1923. return true;
  1924. }
  1925.  
  1926. //***********************************************************************
  1927. // Implementation of the Lucas Strong Pseudo Prime test.
  1928. //
  1929. // Let n be an odd number with gcd(n,D) = 1, and n - J(D, n) = 2^s * d
  1930. // with d odd and s >= 0.
  1931. //
  1932. // If Ud mod n = 0 or V2^r*d mod n = 0 for some 0 <= r < s, then n
  1933. // is a strong Lucas pseudoprime with parameters (P, Q). We select
  1934. // P and Q based on Selfridge.
  1935. //
  1936. // Returns True if number is a strong Lucus pseudo prime.
  1937. // Otherwise, returns False indicating that number is composite.
  1938. //***********************************************************************
  1939.  
  1940. public bool LucasStrongTest()
  1941. {
  1942. BigInteger thisVal;
  1943. if ((this.data[maxLength - ] & 0x80000000) != ) // negative
  1944. thisVal = -this;
  1945. else
  1946. thisVal = this;
  1947.  
  1948. if (thisVal.DataLength == )
  1949. {
  1950. // test small numbers
  1951. if (thisVal.data[] == || thisVal.data[] == )
  1952. return false;
  1953. else if (thisVal.data[] == || thisVal.data[] == )
  1954. return true;
  1955. }
  1956.  
  1957. if ((thisVal.data[] & 0x1) == ) // even numbers
  1958. return false;
  1959.  
  1960. return LucasStrongTestHelper(thisVal);
  1961. }
  1962.  
  1963. private bool LucasStrongTestHelper(BigInteger thisVal)
  1964. {
  1965. // Do the test (selects D based on Selfridge)
  1966. // Let D be the first element of the sequence
  1967. // 5, -7, 9, -11, 13, ... for which J(D,n) = -1
  1968. // Let P = 1, Q = (1-D) / 4
  1969.  
  1970. long D = , sign = -, dCount = ;
  1971. bool done = false;
  1972.  
  1973. while (!done)
  1974. {
  1975. int Jresult = BigInteger.Jacobi(D, thisVal);
  1976.  
  1977. if (Jresult == -)
  1978. done = true; // J(D, this) = 1
  1979. else
  1980. {
  1981. if (Jresult == && Math.Abs(D) < thisVal) // divisor found
  1982. return false;
  1983.  
  1984. if (dCount == )
  1985. {
  1986. // check for square
  1987. BigInteger root = thisVal.sqrt();
  1988. if (root * root == thisVal)
  1989. return false;
  1990. }
  1991.  
  1992. //Console.WriteLine(D);
  1993. D = (Math.Abs(D) + ) * sign;
  1994. sign = -sign;
  1995. }
  1996. dCount++;
  1997. }
  1998.  
  1999. long Q = ( - D) >> ;
  2000.  
  2001. /*
  2002. Console.WriteLine("D = " + D);
  2003. Console.WriteLine("Q = " + Q);
  2004. Console.WriteLine("(n,D) = " + thisVal.gcd(D));
  2005. Console.WriteLine("(n,Q) = " + thisVal.gcd(Q));
  2006. Console.WriteLine("J(D|n) = " + BigInteger.Jacobi(D, thisVal));
  2007. */
  2008.  
  2009. BigInteger p_add1 = thisVal + ;
  2010. int s = ;
  2011.  
  2012. for (int index = ; index < p_add1.DataLength; index++)
  2013. {
  2014. uint mask = 0x01;
  2015.  
  2016. for (int i = ; i < ; i++)
  2017. {
  2018. if ((p_add1.data[index] & mask) != )
  2019. {
  2020. index = p_add1.DataLength; // to break the outer loop
  2021. break;
  2022. }
  2023. mask <<= ;
  2024. s++;
  2025. }
  2026. }
  2027.  
  2028. BigInteger t = p_add1 >> s;
  2029.  
  2030. // calculate constant = b^(2k) / m
  2031. // for Barrett Reduction
  2032. BigInteger constant = new BigInteger();
  2033.  
  2034. int nLen = thisVal.DataLength << ;
  2035. constant.data[nLen] = 0x00000001;
  2036. constant.DataLength = nLen + ;
  2037.  
  2038. constant = constant / thisVal;
  2039.  
  2040. BigInteger[] lucas = LucasSequenceHelper(, Q, t, thisVal, constant, );
  2041. bool isPrime = false;
  2042.  
  2043. if ((lucas[].DataLength == && lucas[].data[] == ) ||
  2044. (lucas[].DataLength == && lucas[].data[] == ))
  2045. {
  2046. // u(t) = 0 or V(t) = 0
  2047. isPrime = true;
  2048. }
  2049.  
  2050. for (int i = ; i < s; i++)
  2051. {
  2052. if (!isPrime)
  2053. {
  2054. // doubling of index
  2055. lucas[] = thisVal.BarrettReduction(lucas[] * lucas[], thisVal, constant);
  2056. lucas[] = (lucas[] - (lucas[] << )) % thisVal;
  2057.  
  2058. //lucas[1] = ((lucas[1] * lucas[1]) - (lucas[2] << 1)) % thisVal;
  2059.  
  2060. if ((lucas[].DataLength == && lucas[].data[] == ))
  2061. isPrime = true;
  2062. }
  2063.  
  2064. lucas[] = thisVal.BarrettReduction(lucas[] * lucas[], thisVal, constant); //Q^k
  2065. }
  2066.  
  2067. if (isPrime) // additional checks for composite numbers
  2068. {
  2069. // If n is prime and gcd(n, Q) == 1, then
  2070. // Q^((n+1)/2) = Q * Q^((n-1)/2) is congruent to (Q * J(Q, n)) mod n
  2071.  
  2072. BigInteger g = thisVal.gcd(Q);
  2073. if (g.DataLength == && g.data[] == ) // gcd(this, Q) == 1
  2074. {
  2075. if ((lucas[].data[maxLength - ] & 0x80000000) != )
  2076. lucas[] += thisVal;
  2077.  
  2078. BigInteger temp = (Q * BigInteger.Jacobi(Q, thisVal)) % thisVal;
  2079. if ((temp.data[maxLength - ] & 0x80000000) != )
  2080. temp += thisVal;
  2081.  
  2082. if (lucas[] != temp)
  2083. isPrime = false;
  2084. }
  2085. }
  2086.  
  2087. return isPrime;
  2088. }
  2089.  
  2090. //***********************************************************************
  2091. // Determines whether a number is probably prime, using the Rabin-Miller's
  2092. // test. Before applying the test, the number is tested for divisibility
  2093. // by primes < 2000
  2094. //
  2095. // Returns true if number is probably prime.
  2096. //***********************************************************************
  2097.  
  2098. public bool isProbablePrime(int confidence)
  2099. {
  2100. BigInteger thisVal;
  2101. if ((this.data[maxLength - ] & 0x80000000) != ) // negative
  2102. thisVal = -this;
  2103. else
  2104. thisVal = this;
  2105.  
  2106. // test for divisibility by primes < 2000
  2107. for (int p = ; p < primesBelow2000.Length; p++)
  2108. {
  2109. BigInteger divisor = primesBelow2000[p];
  2110.  
  2111. if (divisor >= thisVal)
  2112. break;
  2113.  
  2114. BigInteger resultNum = thisVal % divisor;
  2115. if (resultNum.IntValue() == )
  2116. {
  2117. /*
  2118. Console.WriteLine("Not prime! Divisible by {0}\n",
  2119. primesBelow2000[p]);
  2120. */
  2121. return false;
  2122. }
  2123. }
  2124.  
  2125. if (thisVal.RabinMillerTest(confidence))
  2126. return true;
  2127. else
  2128. {
  2129. //Console.WriteLine("Not prime! Failed primality test\n");
  2130. return false;
  2131. }
  2132. }
  2133.  
  2134. //***********************************************************************
  2135. // Determines whether this BigInteger is probably prime using a
  2136. // combination of base 2 strong pseudoprime test and Lucas strong
  2137. // pseudoprime test.
  2138. //
  2139. // The sequence of the primality test is as follows,
  2140. //
  2141. // 1) Trial divisions are carried out using prime numbers below 2000.
  2142. // if any of the primes divides this BigInteger, then it is not prime.
  2143. //
  2144. // 2) Perform base 2 strong pseudoprime test. If this BigInteger is a
  2145. // base 2 strong pseudoprime, proceed on to the next step.
  2146. //
  2147. // 3) Perform strong Lucas pseudoprime test.
  2148. //
  2149. // Returns True if this BigInteger is both a base 2 strong pseudoprime
  2150. // and a strong Lucas pseudoprime.
  2151. //
  2152. // For a detailed discussion of this primality test, see [6].
  2153. //
  2154. //***********************************************************************
  2155.  
  2156. public bool isProbablePrime()
  2157. {
  2158. BigInteger thisVal;
  2159. if ((this.data[maxLength - ] & 0x80000000) != ) // negative
  2160. thisVal = -this;
  2161. else
  2162. thisVal = this;
  2163.  
  2164. if (thisVal.DataLength == )
  2165. {
  2166. // test small numbers
  2167. if (thisVal.data[] == || thisVal.data[] == )
  2168. return false;
  2169. else if (thisVal.data[] == || thisVal.data[] == )
  2170. return true;
  2171. }
  2172.  
  2173. if ((thisVal.data[] & 0x1) == ) // even numbers
  2174. return false;
  2175.  
  2176. // test for divisibility by primes < 2000
  2177. for (int p = ; p < primesBelow2000.Length; p++)
  2178. {
  2179. BigInteger divisor = primesBelow2000[p];
  2180.  
  2181. if (divisor >= thisVal)
  2182. break;
  2183.  
  2184. BigInteger resultNum = thisVal % divisor;
  2185. if (resultNum.IntValue() == )
  2186. {
  2187. //Console.WriteLine("Not prime! Divisible by {0}\n",
  2188. // primesBelow2000[p]);
  2189.  
  2190. return false;
  2191. }
  2192. }
  2193.  
  2194. // Perform BASE 2 Rabin-Miller Test
  2195.  
  2196. // calculate values of s and t
  2197. BigInteger p_sub1 = thisVal - (new BigInteger());
  2198. int s = ;
  2199.  
  2200. for (int index = ; index < p_sub1.DataLength; index++)
  2201. {
  2202. uint mask = 0x01;
  2203.  
  2204. for (int i = ; i < ; i++)
  2205. {
  2206. if ((p_sub1.data[index] & mask) != )
  2207. {
  2208. index = p_sub1.DataLength; // to break the outer loop
  2209. break;
  2210. }
  2211. mask <<= ;
  2212. s++;
  2213. }
  2214. }
  2215.  
  2216. BigInteger t = p_sub1 >> s;
  2217.  
  2218. int bits = thisVal.bitCount();
  2219. BigInteger a = ;
  2220.  
  2221. // b = a^t mod p
  2222. BigInteger b = a.modPow(t, thisVal);
  2223. bool result = false;
  2224.  
  2225. if (b.DataLength == && b.data[] == ) // a^t mod p = 1
  2226. result = true;
  2227.  
  2228. for (int j = ; result == false && j < s; j++)
  2229. {
  2230. if (b == p_sub1) // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
  2231. {
  2232. result = true;
  2233. break;
  2234. }
  2235.  
  2236. b = (b * b) % thisVal;
  2237. }
  2238.  
  2239. // if number is strong pseudoprime to base 2, then do a strong lucas test
  2240. if (result)
  2241. result = LucasStrongTestHelper(thisVal);
  2242.  
  2243. return result;
  2244. }
  2245.  
  2246. //***********************************************************************
  2247. // Returns the lowest 4 bytes of the BigInteger as an int.
  2248. //***********************************************************************
  2249.  
  2250. public int IntValue()
  2251. {
  2252. return (int)data[];
  2253. }
  2254.  
  2255. //***********************************************************************
  2256. // Returns the lowest 8 bytes of the BigInteger as a long.
  2257. //***********************************************************************
  2258.  
  2259. public long LongValue()
  2260. {
  2261. long val = ;
  2262.  
  2263. val = (long)data[];
  2264. try
  2265. { // exception if maxLength = 1
  2266. val |= (long)data[] << ;
  2267. }
  2268. catch (Exception)
  2269. {
  2270. if ((data[] & 0x80000000) != ) // negative
  2271. val = (int)data[];
  2272. }
  2273.  
  2274. return val;
  2275. }
  2276.  
  2277. //***********************************************************************
  2278. // Computes the Jacobi Symbol for a and b.
  2279. // Algorithm adapted from [3] and [4] with some optimizations
  2280. //***********************************************************************
  2281.  
  2282. public static int Jacobi(BigInteger a, BigInteger b)
  2283. {
  2284. // Jacobi defined only for odd integers
  2285. if ((b.data[] & 0x1) == )
  2286. throw (new ArgumentException("Jacobi defined only for odd integers."));
  2287.  
  2288. if (a >= b) a %= b;
  2289. if (a.DataLength == && a.data[] == ) return ; // a == 0
  2290. if (a.DataLength == && a.data[] == ) return ; // a == 1
  2291.  
  2292. if (a < )
  2293. {
  2294. if ((((b - ).data[]) & 0x2) == ) //if( (((b-1) >> 1).data[0] & 0x1) == 0)
  2295. return Jacobi(-a, b);
  2296. else
  2297. return -Jacobi(-a, b);
  2298. }
  2299.  
  2300. int e = ;
  2301. for (int index = ; index < a.DataLength; index++)
  2302. {
  2303. uint mask = 0x01;
  2304.  
  2305. for (int i = ; i < ; i++)
  2306. {
  2307. if ((a.data[index] & mask) != )
  2308. {
  2309. index = a.DataLength; // to break the outer loop
  2310. break;
  2311. }
  2312. mask <<= ;
  2313. e++;
  2314. }
  2315. }
  2316.  
  2317. BigInteger a1 = a >> e;
  2318.  
  2319. int s = ;
  2320. if ((e & 0x1) != && ((b.data[] & 0x7) == || (b.data[] & 0x7) == ))
  2321. s = -;
  2322.  
  2323. if ((b.data[] & 0x3) == && (a1.data[] & 0x3) == )
  2324. s = -s;
  2325.  
  2326. if (a1.DataLength == && a1.data[] == )
  2327. return s;
  2328. else
  2329. return (s * Jacobi(b % a1, a1));
  2330. }
  2331.  
  2332. //***********************************************************************
  2333. // Generates a positive BigInteger that is probably prime.
  2334. //***********************************************************************
  2335.  
  2336. public static BigInteger genPseudoPrime(int bits, int confidence, Random rand)
  2337. {
  2338. BigInteger result = new BigInteger();
  2339. bool done = false;
  2340.  
  2341. while (!done)
  2342. {
  2343. result.genRandomBits(bits, rand);
  2344. result.data[] |= 0x01; // make it odd
  2345.  
  2346. // prime test
  2347. done = result.isProbablePrime(confidence);
  2348. }
  2349. return result;
  2350. }
  2351.  
  2352. //***********************************************************************
  2353. // Generates a random number with the specified number of bits such
  2354. // that gcd(number, this) = 1
  2355. //***********************************************************************
  2356.  
  2357. public BigInteger genCoPrime(int bits, Random rand)
  2358. {
  2359. bool done = false;
  2360. BigInteger result = new BigInteger();
  2361.  
  2362. while (!done)
  2363. {
  2364. result.genRandomBits(bits, rand);
  2365. //Console.WriteLine(result.ToString(16));
  2366.  
  2367. // gcd test
  2368. BigInteger g = result.gcd(this);
  2369. if (g.DataLength == && g.data[] == )
  2370. done = true;
  2371. }
  2372.  
  2373. return result;
  2374. }
  2375.  
  2376. //***********************************************************************
  2377. // Returns the modulo inverse of this. Throws ArithmeticException if
  2378. // the inverse does not exist. (i.e. gcd(this, modulus) != 1)
  2379. //***********************************************************************
  2380.  
  2381. public BigInteger modInverse(BigInteger modulus)
  2382. {
  2383. BigInteger[] p = { , };
  2384. BigInteger[] q = new BigInteger[]; // quotients
  2385. BigInteger[] r = { , }; // remainders
  2386.  
  2387. int step = ;
  2388.  
  2389. BigInteger a = modulus;
  2390. BigInteger b = this;
  2391.  
  2392. while (b.DataLength > || (b.DataLength == && b.data[] != ))
  2393. {
  2394. BigInteger quotient = new BigInteger();
  2395. BigInteger remainder = new BigInteger();
  2396.  
  2397. if (step > )
  2398. {
  2399. BigInteger pval = (p[] - (p[] * q[])) % modulus;
  2400. p[] = p[];
  2401. p[] = pval;
  2402. }
  2403.  
  2404. if (b.DataLength == )
  2405. singleByteDivide(a, b, quotient, remainder);
  2406. else
  2407. multiByteDivide(a, b, quotient, remainder);
  2408.  
  2409. /*
  2410. Console.WriteLine(quotient.dataLength);
  2411. Console.WriteLine("{0} = {1}({2}) + {3} p = {4}", a.ToString(10),
  2412. b.ToString(10), quotient.ToString(10), remainder.ToString(10),
  2413. p[1].ToString(10));
  2414. */
  2415.  
  2416. q[] = q[];
  2417. r[] = r[];
  2418. q[] = quotient; r[] = remainder;
  2419.  
  2420. a = b;
  2421. b = remainder;
  2422.  
  2423. step++;
  2424. }
  2425.  
  2426. if (r[].DataLength > || (r[].DataLength == && r[].data[] != ))
  2427. throw (new ArithmeticException("No inverse!"));
  2428.  
  2429. BigInteger result = ((p[] - (p[] * q[])) % modulus);
  2430.  
  2431. if ((result.data[maxLength - ] & 0x80000000) != )
  2432. result += modulus; // get the least positive modulus
  2433.  
  2434. return result;
  2435. }
  2436.  
  2437. //***********************************************************************
  2438. // Returns the value of the BigInteger as a byte array. The lowest
  2439. // index contains the MSB.
  2440. //***********************************************************************
  2441.  
  2442. public byte[] getBytes()
  2443. {
  2444. int numBits = bitCount();
  2445.  
  2446. int numBytes = numBits >> ;
  2447. if ((numBits & 0x7) != )
  2448. numBytes++;
  2449.  
  2450. byte[] result = new byte[numBytes];
  2451.  
  2452. //Console.WriteLine(result.Length);
  2453.  
  2454. int pos = ;
  2455. uint tempVal, val = data[DataLength - ];
  2456.  
  2457. if ((tempVal = (val >> & 0xFF)) != )
  2458. result[pos++] = (byte)tempVal;
  2459. if ((tempVal = (val >> & 0xFF)) != )
  2460. result[pos++] = (byte)tempVal;
  2461. if ((tempVal = (val >> & 0xFF)) != )
  2462. result[pos++] = (byte)tempVal;
  2463. if ((tempVal = (val & 0xFF)) != )
  2464. result[pos++] = (byte)tempVal;
  2465.  
  2466. for (int i = DataLength - ; i >= ; i--, pos += )
  2467. {
  2468. val = data[i];
  2469. result[pos + ] = (byte)(val & 0xFF);
  2470. val >>= ;
  2471. result[pos + ] = (byte)(val & 0xFF);
  2472. val >>= ;
  2473. result[pos + ] = (byte)(val & 0xFF);
  2474. val >>= ;
  2475. result[pos] = (byte)(val & 0xFF);
  2476. }
  2477.  
  2478. return result;
  2479. }
  2480.  
  2481. //***********************************************************************
  2482. // Sets the value of the specified bit to 1
  2483. // The Least Significant Bit position is 0.
  2484. //***********************************************************************
  2485.  
  2486. public void setBit(uint bitNum)
  2487. {
  2488. uint bytePos = bitNum >> ; // divide by 32
  2489. byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
  2490.  
  2491. uint mask = (uint) << bitPos;
  2492. this.data[bytePos] |= mask;
  2493.  
  2494. if (bytePos >= this.DataLength)
  2495. this.DataLength = (int)bytePos + ;
  2496. }
  2497.  
  2498. //***********************************************************************
  2499. // Sets the value of the specified bit to 0
  2500. // The Least Significant Bit position is 0.
  2501. //***********************************************************************
  2502.  
  2503. public void unsetBit(uint bitNum)
  2504. {
  2505. uint bytePos = bitNum >> ;
  2506.  
  2507. if (bytePos < this.DataLength)
  2508. {
  2509. byte bitPos = (byte)(bitNum & 0x1F);
  2510.  
  2511. uint mask = (uint) << bitPos;
  2512. uint mask2 = 0xFFFFFFFF ^ mask;
  2513.  
  2514. this.data[bytePos] &= mask2;
  2515.  
  2516. if (this.DataLength > && this.data[this.DataLength - ] == )
  2517. this.DataLength--;
  2518. }
  2519. }
  2520.  
  2521. //***********************************************************************
  2522. // Returns a value that is equivalent to the integer square root
  2523. // of the BigInteger.
  2524. //
  2525. // The integer square root of "this" is defined as the largest integer n
  2526. // such that (n * n) <= this
  2527. //
  2528. //***********************************************************************
  2529.  
  2530. public BigInteger sqrt()
  2531. {
  2532. uint numBits = (uint)this.bitCount();
  2533.  
  2534. if ((numBits & 0x1) != ) // odd number of bits
  2535. numBits = (numBits >> ) + ;
  2536. else
  2537. numBits = (numBits >> );
  2538.  
  2539. uint bytePos = numBits >> ;
  2540. byte bitPos = (byte)(numBits & 0x1F);
  2541.  
  2542. uint mask;
  2543.  
  2544. BigInteger result = new BigInteger();
  2545. if (bitPos == )
  2546. mask = 0x80000000;
  2547. else
  2548. {
  2549. mask = (uint) << bitPos;
  2550. bytePos++;
  2551. }
  2552. result.DataLength = (int)bytePos;
  2553.  
  2554. for (int i = (int)bytePos - ; i >= ; i--)
  2555. {
  2556. while (mask != )
  2557. {
  2558. // guess
  2559. result.data[i] ^= mask;
  2560.  
  2561. // undo the guess if its square is larger than this
  2562. if ((result * result) > this)
  2563. result.data[i] ^= mask;
  2564.  
  2565. mask >>= ;
  2566. }
  2567. mask = 0x80000000;
  2568. }
  2569. return result;
  2570. }
  2571.  
  2572. //***********************************************************************
  2573. // Returns the k_th number in the Lucas Sequence reduced modulo n.
  2574. //
  2575. // Uses index doubling to speed up the process. For example, to calculate V(k),
  2576. // we maintain two numbers in the sequence V(n) and V(n+1).
  2577. //
  2578. // To obtain V(2n), we use the identity
  2579. // V(2n) = (V(n) * V(n)) - (2 * Q^n)
  2580. // To obtain V(2n+1), we first write it as
  2581. // V(2n+1) = V((n+1) + n)
  2582. // and use the identity
  2583. // V(m+n) = V(m) * V(n) - Q * V(m-n)
  2584. // Hence,
  2585. // V((n+1) + n) = V(n+1) * V(n) - Q^n * V((n+1) - n)
  2586. // = V(n+1) * V(n) - Q^n * V(1)
  2587. // = V(n+1) * V(n) - Q^n * P
  2588. //
  2589. // We use k in its binary expansion and perform index doubling for each
  2590. // bit position. For each bit position that is set, we perform an
  2591. // index doubling followed by an index addition. This means that for V(n),
  2592. // we need to update it to V(2n+1). For V(n+1), we need to update it to
  2593. // V((2n+1)+1) = V(2*(n+1))
  2594. //
  2595. // This function returns
  2596. // [0] = U(k)
  2597. // [1] = V(k)
  2598. // [2] = Q^n
  2599. //
  2600. // Where U(0) = 0 % n, U(1) = 1 % n
  2601. // V(0) = 2 % n, V(1) = P % n
  2602. //***********************************************************************
  2603.  
  2604. public static BigInteger[] LucasSequence(BigInteger P, BigInteger Q,
  2605. BigInteger k, BigInteger n)
  2606. {
  2607. if (k.DataLength == && k.data[] == )
  2608. {
  2609. BigInteger[] result = new BigInteger[];
  2610.  
  2611. result[] = ; result[] = % n; result[] = % n;
  2612. return result;
  2613. }
  2614.  
  2615. // calculate constant = b^(2k) / m
  2616. // for Barrett Reduction
  2617. BigInteger constant = new BigInteger();
  2618.  
  2619. int nLen = n.DataLength << ;
  2620. constant.data[nLen] = 0x00000001;
  2621. constant.DataLength = nLen + ;
  2622.  
  2623. constant = constant / n;
  2624.  
  2625. // calculate values of s and t
  2626. int s = ;
  2627.  
  2628. for (int index = ; index < k.DataLength; index++)
  2629. {
  2630. uint mask = 0x01;
  2631.  
  2632. for (int i = ; i < ; i++)
  2633. {
  2634. if ((k.data[index] & mask) != )
  2635. {
  2636. index = k.DataLength; // to break the outer loop
  2637. break;
  2638. }
  2639. mask <<= ;
  2640. s++;
  2641. }
  2642. }
  2643.  
  2644. BigInteger t = k >> s;
  2645.  
  2646. //Console.WriteLine("s = " + s + " t = " + t);
  2647. return LucasSequenceHelper(P, Q, t, n, constant, s);
  2648. }
  2649.  
  2650. //***********************************************************************
  2651. // Performs the calculation of the kth term in the Lucas Sequence.
  2652. // For details of the algorithm, see reference [9].
  2653. //
  2654. // k must be odd. i.e LSB == 1
  2655. //***********************************************************************
  2656.  
  2657. private static BigInteger[] LucasSequenceHelper(BigInteger P, BigInteger Q,
  2658. BigInteger k, BigInteger n,
  2659. BigInteger constant, int s)
  2660. {
  2661. BigInteger[] result = new BigInteger[];
  2662.  
  2663. if ((k.data[] & 0x00000001) == )
  2664. throw (new ArgumentException("Argument k must be odd."));
  2665.  
  2666. int numbits = k.bitCount();
  2667. uint mask = (uint)0x1 << ((numbits & 0x1F) - );
  2668.  
  2669. // v = v0, v1 = v1, u1 = u1, Q_k = Q^0
  2670.  
  2671. BigInteger v = % n, Q_k = % n,
  2672. v1 = P % n, u1 = Q_k;
  2673. bool flag = true;
  2674.  
  2675. for (int i = k.DataLength - ; i >= ; i--) // iterate on the binary expansion of k
  2676. {
  2677. //Console.WriteLine("round");
  2678. while (mask != )
  2679. {
  2680. if (i == && mask == 0x00000001) // last bit
  2681. break;
  2682.  
  2683. if ((k.data[i] & mask) != ) // bit is set
  2684. {
  2685. // index doubling with addition
  2686.  
  2687. u1 = (u1 * v1) % n;
  2688.  
  2689. v = ((v * v1) - (P * Q_k)) % n;
  2690. v1 = n.BarrettReduction(v1 * v1, n, constant);
  2691. v1 = (v1 - ((Q_k * Q) << )) % n;
  2692.  
  2693. if (flag)
  2694. flag = false;
  2695. else
  2696. Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);
  2697.  
  2698. Q_k = (Q_k * Q) % n;
  2699. }
  2700. else
  2701. {
  2702. // index doubling
  2703. u1 = ((u1 * v) - Q_k) % n;
  2704.  
  2705. v1 = ((v * v1) - (P * Q_k)) % n;
  2706. v = n.BarrettReduction(v * v, n, constant);
  2707. v = (v - (Q_k << )) % n;
  2708.  
  2709. if (flag)
  2710. {
  2711. Q_k = Q % n;
  2712. flag = false;
  2713. }
  2714. else
  2715. Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);
  2716. }
  2717.  
  2718. mask >>= ;
  2719. }
  2720. mask = 0x80000000;
  2721. }
  2722.  
  2723. // at this point u1 = u(n+1) and v = v(n)
  2724. // since the last bit always 1, we need to transform u1 to u(2n+1) and v to v(2n+1)
  2725.  
  2726. u1 = ((u1 * v) - Q_k) % n;
  2727. v = ((v * v1) - (P * Q_k)) % n;
  2728. if (flag)
  2729. flag = false;
  2730. else
  2731. Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);
  2732.  
  2733. Q_k = (Q_k * Q) % n;
  2734.  
  2735. for (int i = ; i < s; i++)
  2736. {
  2737. // index doubling
  2738. u1 = (u1 * v) % n;
  2739. v = ((v * v) - (Q_k << )) % n;
  2740.  
  2741. if (flag)
  2742. {
  2743. Q_k = Q % n;
  2744. flag = false;
  2745. }
  2746. else
  2747. Q_k = n.BarrettReduction(Q_k * Q_k, n, constant);
  2748. }
  2749.  
  2750. result[] = u1;
  2751. result[] = v;
  2752. result[] = Q_k;
  2753.  
  2754. return result;
  2755. }
  2756.  
  2757. //***********************************************************************
  2758. // Tests the correct implementation of the /, %, * and + operators
  2759. //***********************************************************************
  2760.  
  2761. public static void MulDivTest(int rounds)
  2762. {
  2763. Random rand = new Random();
  2764. byte[] val = new byte[];
  2765. byte[] val2 = new byte[];
  2766.  
  2767. for (int count = ; count < rounds; count++)
  2768. {
  2769. // generate 2 numbers of random length
  2770. int t1 = ;
  2771. while (t1 == )
  2772. t1 = (int)(rand.NextDouble() * );
  2773.  
  2774. int t2 = ;
  2775. while (t2 == )
  2776. t2 = (int)(rand.NextDouble() * );
  2777.  
  2778. bool done = false;
  2779. while (!done)
  2780. {
  2781. for (int i = ; i < ; i++)
  2782. {
  2783. if (i < t1)
  2784. val[i] = (byte)(rand.NextDouble() * );
  2785. else
  2786. val[i] = ;
  2787.  
  2788. if (val[i] != )
  2789. done = true;
  2790. }
  2791. }
  2792.  
  2793. done = false;
  2794. while (!done)
  2795. {
  2796. for (int i = ; i < ; i++)
  2797. {
  2798. if (i < t2)
  2799. val2[i] = (byte)(rand.NextDouble() * );
  2800. else
  2801. val2[i] = ;
  2802.  
  2803. if (val2[i] != )
  2804. done = true;
  2805. }
  2806. }
  2807.  
  2808. while (val[] == )
  2809. val[] = (byte)(rand.NextDouble() * );
  2810. while (val2[] == )
  2811. val2[] = (byte)(rand.NextDouble() * );
  2812.  
  2813. Console.WriteLine(count);
  2814. BigInteger bn1 = new BigInteger(val, t1);
  2815. BigInteger bn2 = new BigInteger(val2, t2);
  2816.  
  2817. // Determine the quotient and remainder by dividing
  2818. // the first number by the second.
  2819.  
  2820. BigInteger bn3 = bn1 / bn2;
  2821. BigInteger bn4 = bn1 % bn2;
  2822.  
  2823. // Recalculate the number
  2824. BigInteger bn5 = (bn3 * bn2) + bn4;
  2825.  
  2826. // Make sure they're the same
  2827. if (bn5 != bn1)
  2828. {
  2829. Console.WriteLine("Error at " + count);
  2830. Console.WriteLine(bn1 + "\n");
  2831. Console.WriteLine(bn2 + "\n");
  2832. Console.WriteLine(bn3 + "\n");
  2833. Console.WriteLine(bn4 + "\n");
  2834. Console.WriteLine(bn5 + "\n");
  2835. return;
  2836. }
  2837. }
  2838. }
  2839.  
  2840. //***********************************************************************
  2841. // Tests the correct implementation of the modulo exponential function
  2842. // using RSA encryption and decryption (using pre-computed encryption and
  2843. // decryption keys).
  2844. //***********************************************************************
  2845.  
  2846. public static void RSATest(int rounds)
  2847. {
  2848. Random rand = new Random();
  2849. byte[] val = new byte[];
  2850.  
  2851. // private and public key
  2852. BigInteger bi_e = new BigInteger("a932b948feed4fb2b692609bd22164fc9edb59fae7880cc1eaff7b3c9626b7e5b241c27a974833b2622ebe09beb451917663d47232488f23a117fc97720f1e7", );
  2853. BigInteger bi_d = new BigInteger("4adf2f7a89da93248509347d2ae506d683dd3a16357e859a980c4f77a4e2f7a01fae289f13a851df6e9db5adaa60bfd2b162bbbe31f7c8f828261a6839311929d2cef4f864dde65e556ce43c89bbbf9f1ac5511315847ce9cc8dc92470a747b8792d6a83b0092d2e5ebaf852c85cacf34278efa99160f2f8aa7ee7214de07b7", );
  2854. BigInteger bi_n = new BigInteger("e8e77781f36a7b3188d711c2190b560f205a52391b3479cdb99fa010745cbeba5f2adc08e1de6bf38398a0487c4a73610d94ec36f17f3f46ad75e17bc1adfec99839589f45f95ccc94cb2a5c500b477eb3323d8cfab0c8458c96f0147a45d27e45a4d11d54d77684f65d48f15fafcc1ba208e71e921b9bd9017c16a5231af7f", );
  2855.  
  2856. Console.WriteLine("e =\n" + bi_e.ToString());
  2857. Console.WriteLine("\nd =\n" + bi_d.ToString());
  2858. Console.WriteLine("\nn =\n" + bi_n.ToString() + "\n");
  2859.  
  2860. for (int count = ; count < rounds; count++)
  2861. {
  2862. // generate data of random length
  2863. int t1 = ;
  2864. while (t1 == )
  2865. t1 = (int)(rand.NextDouble() * );
  2866.  
  2867. bool done = false;
  2868. while (!done)
  2869. {
  2870. for (int i = ; i < ; i++)
  2871. {
  2872. if (i < t1)
  2873. val[i] = (byte)(rand.NextDouble() * );
  2874. else
  2875. val[i] = ;
  2876.  
  2877. if (val[i] != )
  2878. done = true;
  2879. }
  2880. }
  2881.  
  2882. while (val[] == )
  2883. val[] = (byte)(rand.NextDouble() * );
  2884.  
  2885. Console.Write("Round = " + count);
  2886.  
  2887. // encrypt and decrypt data
  2888. BigInteger bi_data = new BigInteger(val, t1);
  2889. BigInteger bi_encrypted = bi_data.modPow(bi_e, bi_n);
  2890. BigInteger bi_decrypted = bi_encrypted.modPow(bi_d, bi_n);
  2891.  
  2892. // compare
  2893. if (bi_decrypted != bi_data)
  2894. {
  2895. Console.WriteLine("\nError at round " + count);
  2896. Console.WriteLine(bi_data + "\n");
  2897. return;
  2898. }
  2899. Console.WriteLine(" <PASSED>.");
  2900. }
  2901.  
  2902. }
  2903.  
  2904. //***********************************************************************
  2905. // Tests the correct implementation of the modulo exponential and
  2906. // inverse modulo functions using RSA encryption and decryption. The two
  2907. // pseudoprimes p and q are fixed, but the two RSA keys are generated
  2908. // for each round of testing.
  2909. //***********************************************************************
  2910.  
  2911. public static void RSATest2(int rounds)
  2912. {
  2913. Random rand = new Random();
  2914. byte[] val = new byte[];
  2915.  
  2916. byte[] pseudoPrime1 = {
  2917. (byte)0x85, (byte)0x84, (byte)0x64, (byte)0xFD, (byte)0x70, (byte)0x6A,
  2918. (byte)0x9F, (byte)0xF0, (byte)0x94, (byte)0x0C, (byte)0x3E, (byte)0x2C,
  2919. (byte)0x74, (byte)0x34, (byte)0x05, (byte)0xC9, (byte)0x55, (byte)0xB3,
  2920. (byte)0x85, (byte)0x32, (byte)0x98, (byte)0x71, (byte)0xF9, (byte)0x41,
  2921. (byte)0x21, (byte)0x5F, (byte)0x02, (byte)0x9E, (byte)0xEA, (byte)0x56,
  2922. (byte)0x8D, (byte)0x8C, (byte)0x44, (byte)0xCC, (byte)0xEE, (byte)0xEE,
  2923. (byte)0x3D, (byte)0x2C, (byte)0x9D, (byte)0x2C, (byte)0x12, (byte)0x41,
  2924. (byte)0x1E, (byte)0xF1, (byte)0xC5, (byte)0x32, (byte)0xC3, (byte)0xAA,
  2925. (byte)0x31, (byte)0x4A, (byte)0x52, (byte)0xD8, (byte)0xE8, (byte)0xAF,
  2926. (byte)0x42, (byte)0xF4, (byte)0x72, (byte)0xA1, (byte)0x2A, (byte)0x0D,
  2927. (byte)0x97, (byte)0xB1, (byte)0x31, (byte)0xB3,
  2928. };
  2929.  
  2930. byte[] pseudoPrime2 = {
  2931. (byte)0x99, (byte)0x98, (byte)0xCA, (byte)0xB8, (byte)0x5E, (byte)0xD7,
  2932. (byte)0xE5, (byte)0xDC, (byte)0x28, (byte)0x5C, (byte)0x6F, (byte)0x0E,
  2933. (byte)0x15, (byte)0x09, (byte)0x59, (byte)0x6E, (byte)0x84, (byte)0xF3,
  2934. (byte)0x81, (byte)0xCD, (byte)0xDE, (byte)0x42, (byte)0xDC, (byte)0x93,
  2935. (byte)0xC2, (byte)0x7A, (byte)0x62, (byte)0xAC, (byte)0x6C, (byte)0xAF,
  2936. (byte)0xDE, (byte)0x74, (byte)0xE3, (byte)0xCB, (byte)0x60, (byte)0x20,
  2937. (byte)0x38, (byte)0x9C, (byte)0x21, (byte)0xC3, (byte)0xDC, (byte)0xC8,
  2938. (byte)0xA2, (byte)0x4D, (byte)0xC6, (byte)0x2A, (byte)0x35, (byte)0x7F,
  2939. (byte)0xF3, (byte)0xA9, (byte)0xE8, (byte)0x1D, (byte)0x7B, (byte)0x2C,
  2940. (byte)0x78, (byte)0xFA, (byte)0xB8, (byte)0x02, (byte)0x55, (byte)0x80,
  2941. (byte)0x9B, (byte)0xC2, (byte)0xA5, (byte)0xCB,
  2942. };
  2943.  
  2944. BigInteger bi_p = new BigInteger(pseudoPrime1);
  2945. BigInteger bi_q = new BigInteger(pseudoPrime2);
  2946. BigInteger bi_pq = (bi_p - ) * (bi_q - );
  2947. BigInteger bi_n = bi_p * bi_q;
  2948.  
  2949. for (int count = ; count < rounds; count++)
  2950. {
  2951. // generate private and public key
  2952. BigInteger bi_e = bi_pq.genCoPrime(, rand);
  2953. BigInteger bi_d = bi_e.modInverse(bi_pq);
  2954.  
  2955. Console.WriteLine("\ne =\n" + bi_e.ToString());
  2956. Console.WriteLine("\nd =\n" + bi_d.ToString());
  2957. Console.WriteLine("\nn =\n" + bi_n.ToString() + "\n");
  2958.  
  2959. // generate data of random length
  2960. int t1 = ;
  2961. while (t1 == )
  2962. t1 = (int)(rand.NextDouble() * );
  2963.  
  2964. bool done = false;
  2965. while (!done)
  2966. {
  2967. for (int i = ; i < ; i++)
  2968. {
  2969. if (i < t1)
  2970. val[i] = (byte)(rand.NextDouble() * );
  2971. else
  2972. val[i] = ;
  2973.  
  2974. if (val[i] != )
  2975. done = true;
  2976. }
  2977. }
  2978.  
  2979. while (val[] == )
  2980. val[] = (byte)(rand.NextDouble() * );
  2981.  
  2982. Console.Write("Round = " + count);
  2983.  
  2984. // encrypt and decrypt data
  2985. BigInteger bi_data = new BigInteger(val, t1);
  2986. BigInteger bi_encrypted = bi_data.modPow(bi_e, bi_n);
  2987. BigInteger bi_decrypted = bi_encrypted.modPow(bi_d, bi_n);
  2988.  
  2989. // compare
  2990. if (bi_decrypted != bi_data)
  2991. {
  2992. Console.WriteLine("\nError at round " + count);
  2993. Console.WriteLine(bi_data + "\n");
  2994. return;
  2995. }
  2996. Console.WriteLine(" <PASSED>.");
  2997. }
  2998.  
  2999. }
  3000.  
  3001. //***********************************************************************
  3002. // Tests the correct implementation of sqrt() method.
  3003. //***********************************************************************
  3004.  
  3005. public static void SqrtTest(int rounds)
  3006. {
  3007. Random rand = new Random();
  3008. for (int count = ; count < rounds; count++)
  3009. {
  3010. // generate data of random length
  3011. int t1 = ;
  3012. while (t1 == )
  3013. t1 = (int)(rand.NextDouble() * );
  3014.  
  3015. Console.Write("Round = " + count);
  3016.  
  3017. BigInteger a = new BigInteger();
  3018. a.genRandomBits(t1, rand);
  3019.  
  3020. BigInteger b = a.sqrt();
  3021. BigInteger c = (b + ) * (b + );
  3022.  
  3023. // check that b is the largest integer such that b*b <= a
  3024. if (c <= a)
  3025. {
  3026. Console.WriteLine("\nError at round " + count);
  3027. Console.WriteLine(a + "\n");
  3028. return;
  3029. }
  3030. Console.WriteLine(" <PASSED>.");
  3031. }
  3032. }
  3033. }
  3034. }

四.总结:

上面主要讲解了非对称加密算法的原理和分类,以及非对称加密算法在.NET中的应用,也对非对称加密算法的.NET底层源码做了分析,希望可以帮助到大家。

加密算法系列:

DotNet加密方式解析--散列加密:http://www.cnblogs.com/pengze0902/p/6268700.html

DotNet加密方式解析--对称加密:http://www.cnblogs.com/pengze0902/p/6268702.html

DotNet加密方式解析--数字签名:http://www.cnblogs.com/pengze0902/p/6268709.html

DotNet加密方式解析--非对称加密:http://www.cnblogs.com/pengze0902/p/6268705.html

DotNet加密方式解析--非对称加密的更多相关文章

  1. 【转】DotNet加密方式解析--非对称加密

    [转]DotNet加密方式解析--非对称加密 新年新气象,也希望新年可以挣大钱.不管今年年底会不会跟去年一样,满怀抱负却又壮志未酬.(不过没事,我已为各位卜上一卦,卦象显示各位都能挣钱...).已经上 ...

  2. DotNet加密方式解析--对称加密

    离过年又近了一天,回家已是近在咫尺,有人欢喜有人愁,因为过几天就得经历每年一度的装逼大戏,亲戚朋友加同学的各方显摆,所以得靠一剂年终奖来装饰一个安稳的年,在这里我想起了一个题目“论装逼的技术性和重要性 ...

  3. DotNet加密方式解析--散列加密

    没时间扯淡类,赶紧上车吧. 在现代社会中,信息安全对于每一个人都是至关重要的,例如我们的银行账户安全.支付宝和微信账户安全.以及邮箱等等,说到信息安全,那就必须得提到加密技术,至于加密的一些相关概念, ...

  4. DotNet加密方式解析--数字签名

    马上就要过年回村里了,村里没有wifi,没有4G,没有流量,更加重要的是过几天电脑就得卖掉换车票了,得赶紧写几篇博客. 数据安全的相关技术在现在愈来愈变得重要,因为人们对于自身的信息都有一种保护的欲望 ...

  5. 【DotNet加密方式解析】-- 好文收藏

    By -- 彭泽 一. DotNet加密方式解析--散列加密 笔记: 散列加密种类: 1.MD5  128位 2.SHA-1  160位 3.SHA-256  256位 4.SHA-384  384位 ...

  6. 如何综合运用对称加密技术、非对称加密技术(公钥密码体制)和Hash函数 保证信息的保密性、完整性、可用性和不可否认性?

    一.几个问题 在提出问题之前,先创建一个使用场景,发送方(甲方)要给接收方(乙方)发送投标书.大家知道,投标书都包括发送方的标的,这个标的是不能被竞标者知晓,更不能被竞标者修改的.在传输的投标书时,提 ...

  7. .NET加密方式解析--散列加密

    在现代社会中,信息安全对于每一个人都是至关重要的,例如我们的银行账户安全.支付宝和微信账户安全.以及邮箱等等,说到信息安全,那就必须得提到加密技术,至于加密的一些相关概念,在这里就不说了. 这一次将会 ...

  8. Java Mail 发送邮件(SSL加密方式,TSL加密方式)

    一.一般配置 发送邮件需要用到  mail包 maven 依赖如下: <!-- https://mvnrepository.com/artifact/javax.mail/mail --> ...

  9. 使用jsencrypt(rsa加密方式)给js加密防被刷

    加密步骤 1.需要加密的参数 * * ).toISOString().replace(/T/g, }Z/, ''); //使用本地时间,然后转换格式 2.js中引用jsencrypt.js文件,然后实 ...

随机推荐

  1. latex题注(caption)位置

    http://anything-is-ok.blog.163.com/blog/static/205720233201301634053760/ 我们以插入图片为例来说明latex中将题注(capti ...

  2. 关于textarea的应用--onchage,onpropertychange,oninput

    oninput,onpropertychange,onchange的用法 1.onchange触发事件必须满足两个条件: a)当前对象属性改变,并且是由键盘或鼠标事件激发的(脚本触发无效) b)当前对 ...

  3. 关于OC和Swift使用GIT创建项目

    1.先进入码云,点击自己的头像 ->   ,2.里面有一个SSH公钥,点击   ,3.之后在终端输入 ssh-keygen -t rsa -C “xxxxx@xxx.com”,注意:”” 要用英 ...

  4. 下标脚本(Swift)

    下标脚本 可以定义在类(Class).结构体(structure)和枚举(enumeration)这些目标中,可以认为是访问集合(collection),列表(list)或序列(sequence的快捷 ...

  5. linux命令学习5-pssh命令

    pssh命令是一个python编写可以在多台服务器上执行命令的工具,同时支持拷贝文件,是同类工具中很出色的,类似pdsh,个人认为相对pdsh更为简便,使用必须在各个服务器上配置好密钥认证访问. 1. ...

  6. vs2012中的小技巧

    解除起始页: 网站(或者叫项目)-属性-启动选项-使用当前页 发布项目: 有些文件在发布的时候,不能发布到指定文件夹中,所以要手动修改该文件的属性 修改两处: 复制到输出目录:始终复制 生成操作:内容

  7. 查看Linux连接数

    netstat  -ant | grep ESTABLISHED  | wc -l

  8. Thinking in scala (1)----类

    ChecksumAccumulator.scala import scala.collection.mutable.Map class ChecksumAccumulator { private va ...

  9. css(三)-- 常用属性

    css的常用属性包括以下几种: CSS 背景CSS 文本CSS 字体CSS 列表CSS 表格 1.CSS 背景 /*操作背景的属性 */ body{ /*background-color:#CCC; ...

  10. adb报错:The connection to adb is down, and a severe&nbs

    我觉得这就像是adb的大姨妈一样,不过处理起来还是很easy滴:  1.报错:BUILD FAILEDD:\workspace\ganji\build.xml:144: The following e ...