SRP6Utilities.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
  8. {
  9. public class Srp6Utilities
  10. {
  11. public static BigInteger CalculateK(IDigest digest, BigInteger N, BigInteger g)
  12. {
  13. return HashPaddedPair(digest, N, N, g);
  14. }
  15. public static BigInteger CalculateU(IDigest digest, BigInteger N, BigInteger A, BigInteger B)
  16. {
  17. return HashPaddedPair(digest, N, A, B);
  18. }
  19. public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
  20. {
  21. byte[] output = new byte[digest.GetDigestSize()];
  22. digest.BlockUpdate(identity, 0, identity.Length);
  23. digest.Update((byte)':');
  24. digest.BlockUpdate(password, 0, password.Length);
  25. digest.DoFinal(output, 0);
  26. digest.BlockUpdate(salt, 0, salt.Length);
  27. digest.BlockUpdate(output, 0, output.Length);
  28. digest.DoFinal(output, 0);
  29. return new BigInteger(1, output);
  30. }
  31. public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random)
  32. {
  33. int minBits = System.Math.Min(256, N.BitLength / 2);
  34. BigInteger min = BigInteger.One.ShiftLeft(minBits - 1);
  35. BigInteger max = N.Subtract(BigInteger.One);
  36. return BigIntegers.CreateRandomInRange(min, max, random);
  37. }
  38. public static BigInteger ValidatePublicValue(BigInteger N, BigInteger val)
  39. {
  40. val = val.Mod(N);
  41. // Check that val % N != 0
  42. if (val.Equals(BigInteger.Zero))
  43. throw new CryptoException("Invalid public value: 0");
  44. return val;
  45. }
  46. /**
  47. * Computes the client evidence message (M1) according to the standard routine:
  48. * M1 = H( A | B | S )
  49. * @param digest The Digest used as the hashing function H
  50. * @param N Modulus used to get the pad length
  51. * @param A The public client value
  52. * @param B The public server value
  53. * @param S The secret calculated by both sides
  54. * @return M1 The calculated client evidence message
  55. */
  56. public static BigInteger CalculateM1(IDigest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S)
  57. {
  58. BigInteger M1 = HashPaddedTriplet(digest, N, A, B, S);
  59. return M1;
  60. }
  61. /**
  62. * Computes the server evidence message (M2) according to the standard routine:
  63. * M2 = H( A | M1 | S )
  64. * @param digest The Digest used as the hashing function H
  65. * @param N Modulus used to get the pad length
  66. * @param A The public client value
  67. * @param M1 The client evidence message
  68. * @param S The secret calculated by both sides
  69. * @return M2 The calculated server evidence message
  70. */
  71. public static BigInteger CalculateM2(IDigest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S)
  72. {
  73. BigInteger M2 = HashPaddedTriplet(digest, N, A, M1, S);
  74. return M2;
  75. }
  76. /**
  77. * Computes the final Key according to the standard routine: Key = H(S)
  78. * @param digest The Digest used as the hashing function H
  79. * @param N Modulus used to get the pad length
  80. * @param S The secret calculated by both sides
  81. * @return
  82. */
  83. public static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S)
  84. {
  85. int padLength = (N.BitLength + 7) / 8;
  86. byte[] _S = GetPadded(S, padLength);
  87. digest.BlockUpdate(_S, 0, _S.Length);
  88. byte[] output = new byte[digest.GetDigestSize()];
  89. digest.DoFinal(output, 0);
  90. return new BigInteger(1, output);
  91. }
  92. private static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3)
  93. {
  94. int padLength = (N.BitLength + 7) / 8;
  95. byte[] n1_bytes = GetPadded(n1, padLength);
  96. byte[] n2_bytes = GetPadded(n2, padLength);
  97. byte[] n3_bytes = GetPadded(n3, padLength);
  98. digest.BlockUpdate(n1_bytes, 0, n1_bytes.Length);
  99. digest.BlockUpdate(n2_bytes, 0, n2_bytes.Length);
  100. digest.BlockUpdate(n3_bytes, 0, n3_bytes.Length);
  101. byte[] output = new byte[digest.GetDigestSize()];
  102. digest.DoFinal(output, 0);
  103. return new BigInteger(1, output);
  104. }
  105. private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2)
  106. {
  107. int padLength = (N.BitLength + 7) / 8;
  108. byte[] n1_bytes = GetPadded(n1, padLength);
  109. byte[] n2_bytes = GetPadded(n2, padLength);
  110. digest.BlockUpdate(n1_bytes, 0, n1_bytes.Length);
  111. digest.BlockUpdate(n2_bytes, 0, n2_bytes.Length);
  112. byte[] output = new byte[digest.GetDigestSize()];
  113. digest.DoFinal(output, 0);
  114. return new BigInteger(1, output);
  115. }
  116. private static byte[] GetPadded(BigInteger n, int length)
  117. {
  118. byte[] bs = BigIntegers.AsUnsignedByteArray(n);
  119. if (bs.Length < length)
  120. {
  121. byte[] tmp = new byte[length];
  122. Array.Copy(bs, 0, tmp, length - bs.Length, bs.Length);
  123. bs = tmp;
  124. }
  125. return bs;
  126. }
  127. }
  128. }
  129. #pragma warning restore
  130. #endif