DHPublicKeyParameters.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math.Raw;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters
  9. {
  10. public class DHPublicKeyParameters
  11. : DHKeyParameters
  12. {
  13. private static BigInteger Validate(BigInteger y, DHParameters dhParams)
  14. {
  15. if (y == null)
  16. throw new ArgumentNullException("y");
  17. BigInteger p = dhParams.P;
  18. // TLS check
  19. if (y.CompareTo(BigInteger.Two) < 0 || y.CompareTo(p.Subtract(BigInteger.Two)) > 0)
  20. throw new ArgumentException("invalid DH public key", "y");
  21. BigInteger q = dhParams.Q;
  22. // We can't validate without Q.
  23. if (q == null)
  24. return y;
  25. if (p.TestBit(0)
  26. && p.BitLength - 1 == q.BitLength
  27. && p.ShiftRight(1).Equals(q))
  28. {
  29. // Safe prime case
  30. if (1 == Legendre(y, p))
  31. return y;
  32. }
  33. else
  34. {
  35. if (BigInteger.One.Equals(y.ModPow(q, p)))
  36. return y;
  37. }
  38. throw new ArgumentException("value does not appear to be in correct group", "y");
  39. }
  40. private readonly BigInteger y;
  41. public DHPublicKeyParameters(
  42. BigInteger y,
  43. DHParameters parameters)
  44. : base(false, parameters)
  45. {
  46. this.y = Validate(y, parameters);
  47. }
  48. public DHPublicKeyParameters(
  49. BigInteger y,
  50. DHParameters parameters,
  51. DerObjectIdentifier algorithmOid)
  52. : base(false, parameters, algorithmOid)
  53. {
  54. this.y = Validate(y, parameters);
  55. }
  56. public virtual BigInteger Y
  57. {
  58. get { return y; }
  59. }
  60. public override bool Equals(
  61. object obj)
  62. {
  63. if (obj == this)
  64. return true;
  65. DHPublicKeyParameters other = obj as DHPublicKeyParameters;
  66. if (other == null)
  67. return false;
  68. return Equals(other);
  69. }
  70. protected bool Equals(
  71. DHPublicKeyParameters other)
  72. {
  73. return y.Equals(other.y) && base.Equals(other);
  74. }
  75. public override int GetHashCode()
  76. {
  77. return y.GetHashCode() ^ base.GetHashCode();
  78. }
  79. private static int Legendre(BigInteger a, BigInteger b)
  80. {
  81. //int r = 0, bits = b.IntValue;
  82. //for (;;)
  83. //{
  84. // int lowestSetBit = a.GetLowestSetBit();
  85. // a = a.ShiftRight(lowestSetBit);
  86. // r ^= (bits ^ (bits >> 1)) & (lowestSetBit << 1);
  87. // int cmp = a.CompareTo(b);
  88. // if (cmp == 0)
  89. // break;
  90. // if (cmp < 0)
  91. // {
  92. // BigInteger t = a; a = b; b = t;
  93. // int oldBits = bits;
  94. // bits = b.IntValue;
  95. // r ^= oldBits & bits;
  96. // }
  97. // a = a.Subtract(b);
  98. //}
  99. //return BigInteger.One.Equals(b) ? (1 - (r & 2)) : 0;
  100. int bitLength = b.BitLength;
  101. uint[] A = Nat.FromBigInteger(bitLength, a);
  102. uint[] B = Nat.FromBigInteger(bitLength, b);
  103. int r = 0;
  104. int len = B.Length;
  105. for (;;)
  106. {
  107. while (A[0] == 0)
  108. {
  109. Nat.ShiftDownWord(len, A, 0);
  110. }
  111. int shift = Integers.NumberOfTrailingZeros((int)A[0]);
  112. if (shift > 0)
  113. {
  114. Nat.ShiftDownBits(len, A, shift, 0);
  115. int bits = (int)B[0];
  116. r ^= (bits ^ (bits >> 1)) & (shift << 1);
  117. }
  118. int cmp = Nat.Compare(len, A, B);
  119. if (cmp == 0)
  120. break;
  121. if (cmp < 0)
  122. {
  123. r ^= (int)(A[0] & B[0]);
  124. uint[] t = A; A = B; B = t;
  125. }
  126. while (A[len - 1] == 0)
  127. {
  128. len = len - 1;
  129. }
  130. Nat.Sub(len, A, B, A);
  131. }
  132. return Nat.IsOne(len, B) ? (1 - (r & 2)) : 0;
  133. }
  134. }
  135. }
  136. #pragma warning restore
  137. #endif