PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Microsoft.Cryptography.Samples.RSAManaged/FlexInt.cs

http://CryptoExtension.codeplex.com
C# | 1930 lines | 1356 code | 389 blank | 185 comment | 313 complexity | 87d6859776232ed71ee844d9e63c4085 MD5 | raw file
Possible License(s): CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Security.Cryptography;
  3. namespace Microsoft.Cryptography
  4. {
  5. internal class FlexInt
  6. {
  7. #region Data Storage
  8. /// <summary>
  9. /// The Length of this FlexInt
  10. /// </summary>
  11. uint length = 1;
  12. /// <summary>
  13. /// The data for this FlexInt
  14. /// </summary>
  15. uint[] data;
  16. #endregion
  17. #region Constants
  18. /// <summary>
  19. /// Default length of a FlexInt in bytes
  20. /// </summary>
  21. const uint DEFAULT_LEN = 20;
  22. /// <summary>
  23. /// Table of primes below 2000. The values were generated using Mathematica 4.1.
  24. /// </summary>
  25. public static readonly uint[] smallPrimes = {
  26. 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
  27. 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
  28. 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
  29. 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
  30. 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
  31. 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
  32. 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
  33. 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
  34. 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
  35. 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
  36. 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
  37. 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
  38. 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181,
  39. 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
  40. 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
  41. 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471,
  42. 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
  43. 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637,
  44. 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
  45. 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867,
  46. 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
  47. 1979, 1987, 1993, 1997, 1999,
  48. 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089,
  49. 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207,
  50. 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
  51. 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389,
  52. 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
  53. 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
  54. 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707,
  55. 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
  56. 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
  57. 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
  58. 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109,
  59. 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
  60. 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329,
  61. 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449,
  62. 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
  63. 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631,
  64. 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
  65. 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
  66. 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943,
  67. 3947, 3967, 3989,
  68. 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091,
  69. 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
  70. 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289,
  71. 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
  72. 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523,
  73. 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
  74. 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759,
  75. 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
  76. 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987,
  77. 4993, 4999,
  78. 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
  79. 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231,
  80. 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
  81. 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449,
  82. 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563,
  83. 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669,
  84. 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
  85. 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869,
  86. 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987
  87. };
  88. public enum Sign : int
  89. {
  90. Negative = -1,
  91. Zero = 0,
  92. Positive = 1
  93. };
  94. #region Exception Messages
  95. private const string ERR_VALUEISNEGATIVE = "This operation would return a negative value.";
  96. #endregion
  97. #endregion
  98. #region Constructors
  99. public FlexInt()
  100. {
  101. data = new uint[DEFAULT_LEN];
  102. this.length = DEFAULT_LEN;
  103. }
  104. public FlexInt(Sign sign, uint len)
  105. {
  106. this.data = new uint[len];
  107. this.length = len;
  108. }
  109. public FlexInt(FlexInt bi)
  110. {
  111. this.data = (uint[])bi.data.Clone();
  112. this.length = bi.length;
  113. }
  114. public FlexInt(FlexInt bi, uint len)
  115. {
  116. this.data = new uint[len];
  117. for (uint i = 0; i < bi.length; i++)
  118. this.data[i] = bi.data[i];
  119. this.length = bi.length;
  120. }
  121. #endregion
  122. #region Conversions
  123. public FlexInt(byte[] inData)
  124. {
  125. length = (uint)inData.Length >> 2;
  126. int leftOver = inData.Length & 0x3;
  127. // length not multiples of 4
  128. if (leftOver != 0) length++;
  129. data = new uint[length];
  130. for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++)
  131. {
  132. data[j] = (uint)(
  133. (inData[i - 3] << (3 * 8)) |
  134. (inData[i - 2] << (2 * 8)) |
  135. (inData[i - 1] << (1 * 8)) |
  136. (inData[i])
  137. );
  138. }
  139. switch (leftOver)
  140. {
  141. case 1: data[length - 1] = (uint)inData[0]; break;
  142. case 2: data[length - 1] = (uint)((inData[0] << 8) | inData[1]); break;
  143. case 3: data[length - 1] = (uint)((inData[0] << 16) | (inData[1] << 8) | inData[2]); break;
  144. }
  145. this.Normalize();
  146. }
  147. public FlexInt(uint[] inData)
  148. {
  149. length = (uint)inData.Length;
  150. data = new uint[length];
  151. for (int i = (int)length - 1, j = 0; i >= 0; i--, j++)
  152. data[j] = inData[i];
  153. this.Normalize();
  154. }
  155. public FlexInt(uint ui)
  156. {
  157. data = new uint[] { ui };
  158. }
  159. public FlexInt(ulong ul)
  160. {
  161. data = new uint[2] { (uint)ul, (uint)(ul >> 32) };
  162. length = 2;
  163. this.Normalize();
  164. }
  165. public static implicit operator FlexInt(uint value)
  166. {
  167. return (new FlexInt(value));
  168. }
  169. public static implicit operator FlexInt(int value)
  170. {
  171. if (value < 0) throw new ArgumentOutOfRangeException("value");
  172. return (new FlexInt((uint)value));
  173. }
  174. public static implicit operator FlexInt(ulong value)
  175. {
  176. return (new FlexInt(value));
  177. }
  178. /* This is the FlexInt.Parse method I use. This method works
  179. because FlexInt.ToString returns the input I gave to Parse. */
  180. public static FlexInt Parse(string number)
  181. {
  182. if (number == null)
  183. throw new ArgumentNullException("number");
  184. int i = 0, len = number.Length;
  185. char c;
  186. bool digits_seen = false;
  187. FlexInt val = new FlexInt(0);
  188. if (number[i] == '+')
  189. {
  190. i++;
  191. }
  192. else if (number[i] == '-')
  193. {
  194. throw new FormatException(ERR_VALUEISNEGATIVE);
  195. }
  196. for (; i < len; i++)
  197. {
  198. c = number[i];
  199. if (c == '\0')
  200. {
  201. i = len;
  202. continue;
  203. }
  204. if (c >= '0' && c <= '9')
  205. {
  206. val = val * 10 + (c - '0');
  207. digits_seen = true;
  208. }
  209. else
  210. {
  211. if (Char.IsWhiteSpace(c))
  212. {
  213. for (i++; i < len; i++)
  214. {
  215. if (!Char.IsWhiteSpace(number[i]))
  216. throw new FormatException();
  217. }
  218. break;
  219. }
  220. else
  221. throw new FormatException();
  222. }
  223. }
  224. if (!digits_seen)
  225. throw new FormatException();
  226. return val;
  227. }
  228. #endregion
  229. #region Operators
  230. public static FlexInt operator +(FlexInt bi1, FlexInt bi2)
  231. {
  232. if (bi1 == 0)
  233. return new FlexInt(bi2);
  234. else if (bi2 == 0)
  235. return new FlexInt(bi1);
  236. else
  237. return PrimitivesHelper.AddSameSign(bi1, bi2);
  238. }
  239. public static FlexInt operator -(FlexInt bi1, FlexInt bi2)
  240. {
  241. if (bi2 == 0)
  242. return new FlexInt(bi1);
  243. if (bi1 == 0)
  244. throw new ArithmeticException(ERR_VALUEISNEGATIVE);
  245. switch (PrimitivesHelper.Compare(bi1, bi2))
  246. {
  247. case Sign.Zero:
  248. return 0;
  249. case Sign.Positive:
  250. return PrimitivesHelper.Subtract(bi1, bi2);
  251. case Sign.Negative:
  252. throw new ArithmeticException(ERR_VALUEISNEGATIVE);
  253. default:
  254. throw new Exception();
  255. }
  256. }
  257. public static int operator %(FlexInt bi, int i)
  258. {
  259. if (i > 0)
  260. return (int)PrimitivesHelper.DwordMod(bi, (uint)i);
  261. else
  262. return -(int)PrimitivesHelper.DwordMod(bi, (uint)-i);
  263. }
  264. public static uint operator %(FlexInt bi, uint ui)
  265. {
  266. return PrimitivesHelper.DwordMod(bi, (uint)ui);
  267. }
  268. public static FlexInt operator %(FlexInt bi1, FlexInt bi2)
  269. {
  270. return PrimitivesHelper.multiByteDivide(bi1, bi2)[1];
  271. }
  272. public static FlexInt operator /(FlexInt bi, int i)
  273. {
  274. if (i > 0)
  275. return PrimitivesHelper.DwordDiv(bi, (uint)i);
  276. throw new ArithmeticException(ERR_VALUEISNEGATIVE);
  277. }
  278. public static FlexInt operator /(FlexInt bi1, FlexInt bi2)
  279. {
  280. return PrimitivesHelper.multiByteDivide(bi1, bi2)[0];
  281. }
  282. public static FlexInt operator *(FlexInt bi1, FlexInt bi2)
  283. {
  284. if (bi1 == 0 || bi2 == 0) return 0;
  285. //
  286. // Validate pointers
  287. //
  288. if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException("bi1 out of range");
  289. if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException("bi2 out of range");
  290. FlexInt ret = new FlexInt(Sign.Positive, bi1.length + bi2.length);
  291. PrimitivesHelper.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);
  292. ret.Normalize();
  293. return ret;
  294. }
  295. public static FlexInt operator <<(FlexInt bi1, int shiftVal)
  296. {
  297. return PrimitivesHelper.LeftShift(bi1, shiftVal);
  298. }
  299. public static FlexInt operator >>(FlexInt bi1, int shiftVal)
  300. {
  301. return PrimitivesHelper.RightShift(bi1, shiftVal);
  302. }
  303. #endregion
  304. #region Friendly names for operators
  305. // with names suggested by FxCop 1.30
  306. public static FlexInt Add(FlexInt bi1, FlexInt bi2)
  307. {
  308. return (bi1 + bi2);
  309. }
  310. public static FlexInt Subtract(FlexInt bi1, FlexInt bi2)
  311. {
  312. return (bi1 - bi2);
  313. }
  314. public static FlexInt Modulus(FlexInt bi1, FlexInt bi2)
  315. {
  316. return (bi1 % bi2);
  317. }
  318. public static FlexInt Divid(FlexInt bi1, FlexInt bi2)
  319. {
  320. return (bi1 / bi2);
  321. }
  322. public static FlexInt Multiply(FlexInt bi1, FlexInt bi2)
  323. {
  324. return (bi1 * bi2);
  325. }
  326. #endregion
  327. #region Bitwise
  328. public int BitCount()
  329. {
  330. this.Normalize();
  331. uint value = data[length - 1];
  332. uint mask = 0x80000000;
  333. uint bits = 32;
  334. while (bits > 0 && (value & mask) == 0)
  335. {
  336. bits--;
  337. mask >>= 1;
  338. }
  339. bits += ((length - 1) << 5);
  340. return (int)bits;
  341. }
  342. /// <summary>
  343. /// Tests if the specified bit is 1.
  344. /// </summary>
  345. /// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
  346. /// <returns>True if bitNum is set to 1, else false.</returns>
  347. public bool TestBit(uint bitNum)
  348. {
  349. uint bytePos = bitNum >> 5; // divide by 32
  350. byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
  351. uint mask = (uint)1 << bitPos;
  352. return ((this.data[bytePos] & mask) != 0);
  353. }
  354. public bool TestBit(int bitNum)
  355. {
  356. if (bitNum < 0) throw new IndexOutOfRangeException("bitNum out of range");
  357. uint bytePos = (uint)bitNum >> 5; // divide by 32
  358. byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
  359. uint mask = (uint)1 << bitPos;
  360. return ((this.data[bytePos] | mask) == this.data[bytePos]);
  361. }
  362. public void SetBit(uint bitNum)
  363. {
  364. SetBit(bitNum, true);
  365. }
  366. public void ClearBit(uint bitNum)
  367. {
  368. SetBit(bitNum, false);
  369. }
  370. public void SetBit(uint bitNum, bool value)
  371. {
  372. uint bytePos = bitNum >> 5; // divide by 32
  373. if (bytePos < this.length)
  374. {
  375. uint mask = (uint)1 << (int)(bitNum & 0x1F);
  376. if (value)
  377. this.data[bytePos] |= mask;
  378. else
  379. this.data[bytePos] &= ~mask;
  380. }
  381. }
  382. public int LowestSetBit()
  383. {
  384. if (this == 0) return -1;
  385. int i = 0;
  386. while (!TestBit(i)) i++;
  387. return i;
  388. }
  389. public byte[] GetBytes()
  390. {
  391. if (this == 0) return new byte[1];
  392. int numBits = BitCount();
  393. int numBytes = numBits >> 3;
  394. if ((numBits & 0x7) != 0)
  395. numBytes++;
  396. byte[] result = new byte[numBytes];
  397. int numBytesInWord = numBytes & 0x3;
  398. if (numBytesInWord == 0) numBytesInWord = 4;
  399. int pos = 0;
  400. for (int i = (int)length - 1; i >= 0; i--)
  401. {
  402. uint val = data[i];
  403. for (int j = numBytesInWord - 1; j >= 0; j--)
  404. {
  405. result[pos + j] = (byte)(val & 0xFF);
  406. val >>= 8;
  407. }
  408. pos += numBytesInWord;
  409. numBytesInWord = 4;
  410. }
  411. return result;
  412. }
  413. #endregion
  414. #region Compare
  415. public static bool operator ==(FlexInt bi1, FlexInt bi2)
  416. {
  417. // we need to compare with null
  418. if ((bi1 as object) == (bi2 as object))
  419. return true;
  420. if (null == bi1 || null == bi2)
  421. return false;
  422. return PrimitivesHelper.Compare(bi1, bi2) == 0;
  423. }
  424. public static bool operator !=(FlexInt bi1, FlexInt bi2)
  425. {
  426. // we need to compare with null
  427. if ((bi1 as object) == (bi2 as object))
  428. return false;
  429. if (null == bi1 || null == bi2)
  430. return true;
  431. return PrimitivesHelper.Compare(bi1, bi2) != 0;
  432. }
  433. public static bool operator >(FlexInt bi1, FlexInt bi2)
  434. {
  435. return PrimitivesHelper.Compare(bi1, bi2) > 0;
  436. }
  437. public static bool operator <(FlexInt bi1, FlexInt bi2)
  438. {
  439. return PrimitivesHelper.Compare(bi1, bi2) < 0;
  440. }
  441. public static bool operator >=(FlexInt bi1, FlexInt bi2)
  442. {
  443. return PrimitivesHelper.Compare(bi1, bi2) >= 0;
  444. }
  445. public static bool operator <=(FlexInt bi1, FlexInt bi2)
  446. {
  447. return PrimitivesHelper.Compare(bi1, bi2) <= 0;
  448. }
  449. public Sign Compare(FlexInt bi)
  450. {
  451. return PrimitivesHelper.Compare(this, bi);
  452. }
  453. #endregion
  454. #region Formatting
  455. public string ToString(uint radix)
  456. {
  457. return ToString(radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  458. }
  459. public string ToString(uint radix, string characterSet)
  460. {
  461. if (characterSet.Length < radix)
  462. throw new ArgumentException("characterSet length is less than radix!", "characterSet");
  463. if (radix == 1)
  464. throw new ArgumentException("Radix '1' is not supported. Radix must be greater or equal '2'", "radix");
  465. if (this == 0) return "0";
  466. if (this == 1) return "1";
  467. string result = "";
  468. FlexInt a = new FlexInt(this);
  469. while (a != 0)
  470. {
  471. uint rem = PrimitivesHelper.SingleByteDivideInPlace(a, radix);
  472. result = characterSet[(int)rem] + result;
  473. }
  474. return result;
  475. }
  476. #endregion
  477. #region Misc
  478. /// <summary>
  479. /// Normalizes this by setting the length to the actual number of
  480. /// uints used in data and by setting the sign to Sign.Zero if the
  481. /// value of this is 0.
  482. /// </summary>
  483. private void Normalize()
  484. {
  485. // Normalize length
  486. while (length > 0 && data[length - 1] == 0) length--;
  487. // Check for zero
  488. if (length == 0)
  489. length++;
  490. }
  491. public void Clear()
  492. {
  493. for (int i = 0; i < length; i++)
  494. data[i] = 0x00;
  495. }
  496. #endregion
  497. #region Object Impl
  498. public override int GetHashCode()
  499. {
  500. uint val = 0;
  501. for (uint i = 0; i < this.length; i++)
  502. val ^= this.data[i];
  503. return (int)val;
  504. }
  505. public override string ToString()
  506. {
  507. return ToString(10);
  508. }
  509. public override bool Equals(object o)
  510. {
  511. if (o == null) return false;
  512. if (o is int) return (int)o >= 0 && this == (uint)o;
  513. return PrimitivesHelper.Compare(this, (FlexInt)o) == 0;
  514. }
  515. #endregion
  516. #region Number Theory
  517. public FlexInt ModPow(FlexInt exp, FlexInt n)
  518. {
  519. ModulusHelper mr = new ModulusHelper(n);
  520. return mr.Pow(this, exp);
  521. }
  522. #endregion
  523. public class ModulusHelper
  524. {
  525. FlexInt mod, constant;
  526. public ModulusHelper(FlexInt modulus)
  527. {
  528. this.mod = modulus;
  529. // calculate constant = b^ (2k) / m
  530. uint i = mod.length << 1;
  531. constant = new FlexInt(Sign.Positive, i + 1);
  532. constant.data[i] = 0x00000001;
  533. constant = constant / mod;
  534. }
  535. public void BarrettReduction(FlexInt x)
  536. {
  537. FlexInt n = mod;
  538. uint k = n.length,
  539. kPlusOne = k + 1,
  540. kMinusOne = k - 1;
  541. // x < mod, so nothing to do.
  542. if (x.length < k) return;
  543. FlexInt q3;
  544. //
  545. // Validate pointers
  546. //
  547. if (x.data.Length < x.length) throw new IndexOutOfRangeException("x out of range");
  548. // q1 = x / b^ (k-1)
  549. // q2 = q1 * constant
  550. // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
  551. // TODO: We should the method in HAC p 604 to do this (14.45)
  552. q3 = new FlexInt(Sign.Positive, x.length - kMinusOne + constant.length);
  553. PrimitivesHelper.Multiply(x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);
  554. // r1 = x mod b^ (k+1)
  555. // i.e. keep the lowest (k+1) words
  556. uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;
  557. x.length = lengthToCopy;
  558. x.Normalize();
  559. // r2 = (q3 * n) mod b^ (k+1)
  560. // partial multiplication of q3 and n
  561. FlexInt r2 = new FlexInt(Sign.Positive, kPlusOne);
  562. PrimitivesHelper.MultiplyMod2p32pmod(q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);
  563. r2.Normalize();
  564. if (r2 <= x)
  565. {
  566. PrimitivesHelper.MinusEq(x, r2);
  567. }
  568. else
  569. {
  570. FlexInt val = new FlexInt(Sign.Positive, kPlusOne + 1);
  571. val.data[kPlusOne] = 0x00000001;
  572. PrimitivesHelper.MinusEq(val, r2);
  573. PrimitivesHelper.PlusEq(x, val);
  574. }
  575. while (x >= n)
  576. PrimitivesHelper.MinusEq(x, n);
  577. }
  578. public FlexInt Multiply(FlexInt a, FlexInt b)
  579. {
  580. if (a == 0 || b == 0) return 0;
  581. if (a.length >= mod.length << 1)
  582. a %= mod;
  583. if (b.length >= mod.length << 1)
  584. b %= mod;
  585. if (a.length >= mod.length)
  586. BarrettReduction(a);
  587. if (b.length >= mod.length)
  588. BarrettReduction(b);
  589. FlexInt ret = new FlexInt(a * b);
  590. BarrettReduction(ret);
  591. return ret;
  592. }
  593. public FlexInt Difference(FlexInt a, FlexInt b)
  594. {
  595. Sign cmp = PrimitivesHelper.Compare(a, b);
  596. FlexInt diff;
  597. switch (cmp)
  598. {
  599. case Sign.Zero:
  600. return 0;
  601. case Sign.Positive:
  602. diff = a - b; break;
  603. case Sign.Negative:
  604. diff = b - a; break;
  605. default:
  606. throw new Exception();
  607. }
  608. if (diff >= mod)
  609. {
  610. if (diff.length >= mod.length << 1)
  611. diff %= mod;
  612. else
  613. BarrettReduction(diff);
  614. }
  615. if (cmp == Sign.Negative)
  616. diff = mod - diff;
  617. return diff;
  618. }
  619. public FlexInt Pow(FlexInt b, FlexInt exp)
  620. {
  621. if ((mod.data[0] & 1) == 1) return OddPow(b, exp);
  622. else return EvenPow(b, exp);
  623. }
  624. public FlexInt EvenPow(FlexInt b, FlexInt exp)
  625. {
  626. FlexInt resultNum = new FlexInt((FlexInt)1, mod.length << 1);
  627. FlexInt tempNum = new FlexInt(b % mod, mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
  628. uint totalBits = (uint)exp.BitCount();
  629. uint[] wkspace = new uint[mod.length << 1];
  630. // perform squaring and multiply exponentiation
  631. for (uint pos = 0; pos < totalBits; pos++)
  632. {
  633. if (exp.TestBit(pos))
  634. {
  635. Array.Clear(wkspace, 0, wkspace.Length);
  636. PrimitivesHelper.Multiply(resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
  637. resultNum.length += tempNum.length;
  638. uint[] t = wkspace;
  639. wkspace = resultNum.data;
  640. resultNum.data = t;
  641. BarrettReduction(resultNum);
  642. }
  643. PrimitivesHelper.SquarePositive(tempNum, ref wkspace);
  644. BarrettReduction(tempNum);
  645. if (tempNum == 1)
  646. {
  647. return resultNum;
  648. }
  649. }
  650. return resultNum;
  651. }
  652. private FlexInt OddPow(FlexInt b, FlexInt exp)
  653. {
  654. FlexInt resultNum = new FlexInt(Montgomery.ToMont(1, mod), mod.length << 1);
  655. FlexInt tempNum = new FlexInt(Montgomery.ToMont(b, mod), mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
  656. uint mPrime = Montgomery.Inverse(mod.data[0]);
  657. uint totalBits = (uint)exp.BitCount();
  658. uint[] wkspace = new uint[mod.length << 1];
  659. // perform squaring and multiply exponentiation
  660. for (uint pos = 0; pos < totalBits; pos++)
  661. {
  662. if (exp.TestBit(pos))
  663. {
  664. Array.Clear(wkspace, 0, wkspace.Length);
  665. PrimitivesHelper.Multiply(resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
  666. resultNum.length += tempNum.length;
  667. uint[] t = wkspace;
  668. wkspace = resultNum.data;
  669. resultNum.data = t;
  670. Montgomery.Reduce(resultNum, mod, mPrime);
  671. }
  672. PrimitivesHelper.SquarePositive(tempNum, ref wkspace);
  673. Montgomery.Reduce(tempNum, mod, mPrime);
  674. }
  675. Montgomery.Reduce(resultNum, mod, mPrime);
  676. return resultNum;
  677. }
  678. #region Pow Small Base
  679. public FlexInt Pow(uint b, FlexInt exp)
  680. {
  681. if ((mod.data[0] & 1) == 1)
  682. return OddPow(b, exp);
  683. else
  684. return EvenPow(b, exp);
  685. }
  686. private unsafe FlexInt OddPow(uint b, FlexInt exp)
  687. {
  688. exp.Normalize();
  689. uint[] wkspace = new uint[mod.length << 1 + 1];
  690. FlexInt resultNum = Montgomery.ToMont((FlexInt)b, this.mod);
  691. resultNum = new FlexInt(resultNum, mod.length << 1 + 1);
  692. uint mPrime = Montgomery.Inverse(mod.data[0]);
  693. uint pos = (uint)exp.BitCount() - 2;
  694. //
  695. // We know that the first itr will make the val b
  696. //
  697. do
  698. {
  699. //
  700. // r = r ^ 2 % m
  701. //
  702. PrimitivesHelper.SquarePositive(resultNum, ref wkspace);
  703. resultNum = Montgomery.Reduce(resultNum, mod, mPrime);
  704. if (exp.TestBit(pos))
  705. {
  706. //
  707. // r = r * b % m
  708. //
  709. fixed (uint* u = resultNum.data)
  710. {
  711. uint i = 0;
  712. ulong mc = 0;
  713. do
  714. {
  715. mc += (ulong)u[i] * (ulong)b;
  716. u[i] = (uint)mc;
  717. mc >>= 32;
  718. } while (++i < resultNum.length);
  719. if (resultNum.length < mod.length)
  720. {
  721. if (mc != 0)
  722. {
  723. u[i] = (uint)mc;
  724. resultNum.length++;
  725. while (resultNum >= mod)
  726. PrimitivesHelper.MinusEq(resultNum, mod);
  727. }
  728. }
  729. else if (mc != 0)
  730. {
  731. //
  732. // First, we estimate the quotient by dividing
  733. // the first part of each of the numbers. Then
  734. // we correct this, if necessary, with a subtraction.
  735. //
  736. uint cc = (uint)mc;
  737. // We would rather have this estimate overshoot,
  738. // so we add one to the divisor
  739. uint divEstimate;
  740. if (mod.data[mod.length - 1] < UInt32.MaxValue)
  741. {
  742. divEstimate = (uint)((((ulong)cc << 32) | (ulong)u[i - 1]) /
  743. (mod.data[mod.length - 1] + 1));
  744. }
  745. else
  746. {
  747. // guess but don't divide by 0
  748. divEstimate = (uint)((((ulong)cc << 32) | (ulong)u[i - 1]) /
  749. (mod.data[mod.length - 1]));
  750. }
  751. uint t;
  752. i = 0;
  753. mc = 0;
  754. do
  755. {
  756. mc += (ulong)mod.data[i] * (ulong)divEstimate;
  757. t = u[i];
  758. u[i] -= (uint)mc;
  759. mc >>= 32;
  760. if (u[i] > t) mc++;
  761. i++;
  762. } while (i < resultNum.length);
  763. cc -= (uint)mc;
  764. if (cc != 0)
  765. {
  766. uint sc = 0, j = 0;
  767. uint[] s = mod.data;
  768. do
  769. {
  770. uint a = s[j];
  771. if (((a += sc) < sc) | ((u[j] -= a) > ~a)) sc = 1;
  772. else sc = 0;
  773. j++;
  774. } while (j < resultNum.length);
  775. cc -= sc;
  776. }
  777. while (resultNum >= mod)
  778. PrimitivesHelper.MinusEq(resultNum, mod);
  779. }
  780. else
  781. {
  782. while (resultNum >= mod)
  783. PrimitivesHelper.MinusEq(resultNum, mod);
  784. }
  785. }
  786. }
  787. } while (pos-- > 0);
  788. resultNum = Montgomery.Reduce(resultNum, mod, mPrime);
  789. return resultNum;
  790. }
  791. private unsafe FlexInt EvenPow(uint b, FlexInt exp)
  792. {
  793. exp.Normalize();
  794. uint[] wkspace = new uint[mod.length << 1 + 1];
  795. FlexInt resultNum = new FlexInt((FlexInt)b, mod.length << 1 + 1);
  796. uint pos = (uint)exp.BitCount() - 2;
  797. //
  798. // We know that the first itr will make the val b
  799. //
  800. do
  801. {
  802. //
  803. // r = r ^ 2 % m
  804. //
  805. PrimitivesHelper.SquarePositive(resultNum, ref wkspace);
  806. if (!(resultNum.length < mod.length))
  807. BarrettReduction(resultNum);
  808. if (exp.TestBit(pos))
  809. {
  810. //
  811. // r = r * b % m
  812. //
  813. fixed (uint* u = resultNum.data)
  814. {
  815. uint i = 0;
  816. ulong mc = 0;
  817. do
  818. {
  819. mc += (ulong)u[i] * (ulong)b;
  820. u[i] = (uint)mc;
  821. mc >>= 32;
  822. } while (++i < resultNum.length);
  823. if (resultNum.length < mod.length)
  824. {
  825. if (mc != 0)
  826. {
  827. u[i] = (uint)mc;
  828. resultNum.length++;
  829. while (resultNum >= mod)
  830. PrimitivesHelper.MinusEq(resultNum, mod);
  831. }
  832. }
  833. else if (mc != 0)
  834. {
  835. //
  836. // First, we estimate the quotient by dividing
  837. // the first part of each of the numbers. Then
  838. // we correct this, if necessary, with a subtraction.
  839. //
  840. uint cc = (uint)mc;
  841. // We would rather have this estimate overshoot,
  842. // so we add one to the divisor
  843. uint divEstimate = (uint)((((ulong)cc << 32) | (ulong)u[i - 1]) /
  844. (mod.data[mod.length - 1] + 1));
  845. uint t;
  846. i = 0;
  847. mc = 0;
  848. do
  849. {
  850. mc += (ulong)mod.data[i] * (ulong)divEstimate;
  851. t = u[i];
  852. u[i] -= (uint)mc;
  853. mc >>= 32;
  854. if (u[i] > t) mc++;
  855. i++;
  856. } while (i < resultNum.length);
  857. cc -= (uint)mc;
  858. if (cc != 0)
  859. {
  860. uint sc = 0, j = 0;
  861. uint[] s = mod.data;
  862. do
  863. {
  864. uint a = s[j];
  865. if (((a += sc) < sc) | ((u[j] -= a) > ~a)) sc = 1;
  866. else sc = 0;
  867. j++;
  868. } while (j < resultNum.length);
  869. cc -= sc;
  870. }
  871. while (resultNum >= mod)
  872. PrimitivesHelper.MinusEq(resultNum, mod);
  873. }
  874. else
  875. {
  876. while (resultNum >= mod)
  877. PrimitivesHelper.MinusEq(resultNum, mod);
  878. }
  879. }
  880. }
  881. } while (pos-- > 0);
  882. return resultNum;
  883. }
  884. #endregion
  885. }
  886. public class Montgomery
  887. {
  888. private Montgomery()
  889. {
  890. }
  891. public static uint Inverse(uint n)
  892. {
  893. uint y = n, z;
  894. while ((z = n * y) != 1)
  895. y *= 2 - z;
  896. return (uint)-y;
  897. }
  898. public static FlexInt ToMont(FlexInt n, FlexInt m)
  899. {
  900. n.Normalize(); m.Normalize();
  901. n <<= (int)m.length * 32;
  902. n %= m;
  903. return n;
  904. }
  905. public static unsafe FlexInt Reduce(FlexInt n, FlexInt m, uint mPrime)
  906. {
  907. FlexInt A = n;
  908. fixed (uint* a = A.data, mm = m.data)
  909. {
  910. for (uint i = 0; i < m.length; i++)
  911. {
  912. // The mod here is taken care of by the CPU,
  913. // since the multiply will overflow.
  914. uint u_i = a[0] * mPrime /* % 2^32 */;
  915. //
  916. // A += u_i * m;
  917. // A >>= 32
  918. //
  919. // mP = Position in mod
  920. // aSP = the source of bits from a
  921. // aDP = destination for bits
  922. uint* mP = mm, aSP = a, aDP = a;
  923. ulong c = (ulong)u_i * ((ulong)*(mP++)) + *(aSP++);
  924. c >>= 32;
  925. uint j = 1;
  926. // Multiply and add
  927. for (; j < m.length; j++)
  928. {
  929. c += (ulong)u_i * (ulong)*(mP++) + *(aSP++);
  930. *(aDP++) = (uint)c;
  931. c >>= 32;
  932. }
  933. // Account for carry
  934. // TODO: use a better loop here, we dont need the ulong stuff
  935. for (; j < A.length; j++)
  936. {
  937. c += *(aSP++);
  938. *(aDP++) = (uint)c;
  939. c >>= 32;
  940. if (c == 0) { j++; break; }
  941. }
  942. // Copy the rest
  943. for (; j < A.length; j++)
  944. {
  945. *(aDP++) = *(aSP++);
  946. }
  947. *(aDP++) = (uint)c;
  948. }
  949. while (A.length > 1 && a[A.length - 1] == 0) A.length--;
  950. }
  951. if (A >= m) PrimitivesHelper.MinusEq(A, m);
  952. return A;
  953. }
  954. }
  955. /// <summary>
  956. /// Low level functions for the FlexInt
  957. /// </summary>
  958. private sealed class PrimitivesHelper
  959. {
  960. #region Addition/Subtraction
  961. /// <summary>
  962. /// Adds two numbers with the same sign.
  963. /// </summary>
  964. /// <param name="bi1">A FlexInt</param>
  965. /// <param name="bi2">A FlexInt</param>
  966. /// <returns>bi1 + bi2</returns>
  967. public static FlexInt AddSameSign(FlexInt bi1, FlexInt bi2)
  968. {
  969. uint[] x, y;
  970. uint yMax, xMax, i = 0;
  971. // x should be bigger
  972. if (bi1.length < bi2.length)
  973. {
  974. x = bi2.data;
  975. xMax = bi2.length;
  976. y = bi1.data;
  977. yMax = bi1.length;
  978. }
  979. else
  980. {
  981. x = bi1.data;
  982. xMax = bi1.length;
  983. y = bi2.data;
  984. yMax = bi2.length;
  985. }
  986. FlexInt result = new FlexInt(Sign.Positive, xMax + 1);
  987. uint[] r = result.data;
  988. ulong sum = 0;
  989. // Add common parts of both numbers
  990. do
  991. {
  992. sum = ((ulong)x[i]) + ((ulong)y[i]) + sum;
  993. r[i] = (uint)sum;
  994. sum >>= 32;
  995. } while (++i < yMax);
  996. // Copy remainder of longer number while carry propagation is required
  997. bool carry = (sum != 0);
  998. if (carry)
  999. {
  1000. if (i < xMax)
  1001. {
  1002. do
  1003. carry = ((r[i] = x[i] + 1) == 0);
  1004. while (++i < xMax && carry);
  1005. }
  1006. if (carry)
  1007. {
  1008. r[i] = 1;
  1009. result.length = ++i;
  1010. return result;
  1011. }
  1012. }
  1013. // Copy the rest
  1014. if (i < xMax)
  1015. {
  1016. do
  1017. r[i] = x[i];
  1018. while (++i < xMax);
  1019. }
  1020. result.Normalize();
  1021. return result;
  1022. }
  1023. public static FlexInt Subtract(FlexInt big, FlexInt small)
  1024. {
  1025. FlexInt result = new FlexInt(Sign.Positive, big.length);
  1026. uint[] r = result.data, b = big.data, s = small.data;
  1027. uint i = 0, c = 0;
  1028. do
  1029. {
  1030. uint x = s[i];
  1031. if (((x += c) < c) | ((r[i] = b[i] - x) > ~x))
  1032. c = 1;
  1033. else
  1034. c = 0;
  1035. } while (++i < small.length);
  1036. if (i == big.length) goto fixup;
  1037. if (c == 1)
  1038. {
  1039. do
  1040. r[i] = b[i] - 1;
  1041. while (b[i++] == 0 && i < big.length);
  1042. if (i == big.length) goto fixup;
  1043. }
  1044. do
  1045. r[i] = b[i];
  1046. while (++i < big.length);
  1047. fixup:
  1048. result.Normalize();
  1049. return result;
  1050. }
  1051. public static void MinusEq(FlexInt big, FlexInt small)
  1052. {
  1053. uint[] b = big.data, s = small.data;
  1054. uint i = 0, c = 0;
  1055. do
  1056. {
  1057. uint x = s[i];
  1058. if (((x += c) < c) | ((b[i] -= x) > ~x))
  1059. c = 1;
  1060. else
  1061. c = 0;
  1062. } while (++i < small.length);
  1063. if (i == big.length) goto fixup;
  1064. if (c == 1)
  1065. {
  1066. do
  1067. b[i]--;
  1068. while (b[i++] == 0 && i < big.length);
  1069. }
  1070. fixup:
  1071. // Normalize length
  1072. while (big.length > 0 && big.data[big.length - 1] == 0) big.length--;
  1073. // Check for zero
  1074. if (big.length == 0)
  1075. big.length++;
  1076. }
  1077. public static void PlusEq(FlexInt bi1, FlexInt bi2)
  1078. {
  1079. uint[] x, y;
  1080. uint yMax, xMax, i = 0;
  1081. bool flag = false;
  1082. // x should be bigger
  1083. if (bi1.length < bi2.length)
  1084. {
  1085. flag = true;
  1086. x = bi2.data;
  1087. xMax = bi2.length;
  1088. y = bi1.data;
  1089. yMax = bi1.length;
  1090. }
  1091. else
  1092. {
  1093. x = bi1.data;
  1094. xMax = bi1.length;
  1095. y = bi2.data;
  1096. yMax = bi2.length;
  1097. }
  1098. uint[] r = bi1.data;
  1099. ulong sum = 0;
  1100. // Add common parts of both numbers
  1101. do
  1102. {
  1103. sum += ((ulong)x[i]) + ((ulong)y[i]);
  1104. r[i] = (uint)sum;
  1105. sum >>= 32;
  1106. } while (++i < yMax);
  1107. // Copy remainder of longer number while carry propagation is required
  1108. bool carry = (sum != 0);
  1109. if (carry)
  1110. {
  1111. if (i < xMax)
  1112. {
  1113. do
  1114. carry = ((r[i] = x[i] + 1) == 0);
  1115. while (++i < xMax && carry);
  1116. }
  1117. if (carry)
  1118. {
  1119. r[i] = 1;
  1120. bi1.length = ++i;
  1121. return;
  1122. }
  1123. }
  1124. // Copy the rest
  1125. if (flag && i < xMax - 1)
  1126. {
  1127. do
  1128. r[i] = x[i];
  1129. while (++i < xMax);
  1130. }
  1131. bi1.length = xMax + 1;
  1132. bi1.Normalize();
  1133. }
  1134. #endregion
  1135. #region Compare
  1136. /// <summary>
  1137. /// Compares two FlexInt
  1138. /// </summary>
  1139. /// <param name="bi1">A FlexInt</param>
  1140. /// <param name="bi2">A FlexInt</param>
  1141. /// <returns>The sign of bi1 - bi2</returns>
  1142. public static Sign Compare(FlexInt bi1, FlexInt bi2)
  1143. {
  1144. //
  1145. // Step 1. Compare the lengths
  1146. //
  1147. uint l1 = bi1.length, l2 = bi2.length;
  1148. while (l1 > 0 && bi1.data[l1 - 1] == 0) l1--;
  1149. while (l2 > 0 && bi2.data[l2 - 1] == 0) l2--;
  1150. if (l1 == 0 && l2 == 0) return Sign.Zero;
  1151. // bi1 len < bi2 len
  1152. if (l1 < l2) return Sign.Negative;
  1153. // bi1 len > bi2 len
  1154. else if (l1 > l2) return Sign.Positive;
  1155. //
  1156. // Step 2. Compare the bits
  1157. //
  1158. uint pos = l1 - 1;
  1159. while (pos != 0 && bi1.data[pos] == bi2.data[pos]) pos--;
  1160. if (bi1.data[pos] < bi2.data[pos])
  1161. return Sign.Negative;
  1162. else if (bi1.data[pos] > bi2.data[pos])
  1163. return Sign.Positive;
  1164. else
  1165. return Sign.Zero;
  1166. }
  1167. #endregion
  1168. #region Division
  1169. #region Dword
  1170. /// <summary>
  1171. /// Performs n / d and n % d in one operation.
  1172. /// </summary>
  1173. /// <param name="n">A FlexInt, upon exit this will hold n / d</param>
  1174. /// <param name="d">The divisor</param>
  1175. /// <returns>n % d</returns>
  1176. public static uint SingleByteDivideInPlace(FlexInt n, uint d)
  1177. {
  1178. ulong r = 0;
  1179. uint i = n.length;
  1180. while (i-- > 0)
  1181. {
  1182. r <<= 32;
  1183. r |= n.data[i];
  1184. n.data[i] = (uint)(r / d);
  1185. r %= d;
  1186. }
  1187. n.Normalize();
  1188. return (uint)r;
  1189. }
  1190. public static uint Dword

Large files files are truncated, but you can click here to view the full file