WNafL2RMultiplier.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. namespace Org.BouncyCastle.Math.EC.Multiplier
  4. {
  5. /**
  6. * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
  7. * algorithm.
  8. */
  9. public class WNafL2RMultiplier
  10. : AbstractECMultiplier
  11. {
  12. /**
  13. * Multiplies <code>this</code> by an integer <code>k</code> using the
  14. * Window NAF method.
  15. * @param k The integer by which <code>this</code> is multiplied.
  16. * @return A new <code>ECPoint</code> which equals <code>this</code>
  17. * multiplied by <code>k</code>.
  18. */
  19. protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
  20. {
  21. // Clamp the window width in the range [2, 16]
  22. int width = System.Math.Max(2, System.Math.Min(16, GetWindowSize(k.BitLength)));
  23. WNafPreCompInfo wnafPreCompInfo = WNafUtilities.Precompute(p, width, true);
  24. ECPoint[] preComp = wnafPreCompInfo.PreComp;
  25. ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg;
  26. int[] wnaf = WNafUtilities.GenerateCompactWindowNaf(width, k);
  27. ECPoint R = p.Curve.Infinity;
  28. int i = wnaf.Length;
  29. /*
  30. * NOTE: We try to optimize the first window using the precomputed points to substitute an
  31. * addition for 2 or more doublings.
  32. */
  33. if (i > 1)
  34. {
  35. int wi = wnaf[--i];
  36. int digit = wi >> 16, zeroes = wi & 0xFFFF;
  37. int n = System.Math.Abs(digit);
  38. ECPoint[] table = digit < 0 ? preCompNeg : preComp;
  39. // Optimization can only be used for values in the lower half of the table
  40. if ((n << 2) < (1 << width))
  41. {
  42. int highest = LongArray.BitLengths[n];
  43. // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
  44. int scale = width - highest;
  45. int lowBits = n ^ (1 << (highest - 1));
  46. int i1 = ((1 << (width - 1)) - 1);
  47. int i2 = (lowBits << scale) + 1;
  48. R = table[i1 >> 1].Add(table[i2 >> 1]);
  49. zeroes -= scale;
  50. //Console.WriteLine("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2);
  51. }
  52. else
  53. {
  54. R = table[n >> 1];
  55. }
  56. R = R.TimesPow2(zeroes);
  57. }
  58. while (i > 0)
  59. {
  60. int wi = wnaf[--i];
  61. int digit = wi >> 16, zeroes = wi & 0xFFFF;
  62. int n = System.Math.Abs(digit);
  63. ECPoint[] table = digit < 0 ? preCompNeg : preComp;
  64. ECPoint r = table[n >> 1];
  65. R = R.TwicePlus(r);
  66. R = R.TimesPow2(zeroes);
  67. }
  68. return R;
  69. }
  70. /**
  71. * Determine window width to use for a scalar multiplication of the given size.
  72. *
  73. * @param bits the bit-length of the scalar to multiply by
  74. * @return the window size to use
  75. */
  76. protected virtual int GetWindowSize(int bits)
  77. {
  78. return WNafUtilities.GetWindowSize(bits);
  79. }
  80. }
  81. }
  82. #endif