SRP6Server.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
  8. {
  9. /**
  10. * Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
  11. * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
  12. * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
  13. */
  14. public class Srp6Server
  15. {
  16. protected BigInteger N;
  17. protected BigInteger g;
  18. protected BigInteger v;
  19. protected SecureRandom random;
  20. protected IDigest digest;
  21. protected BigInteger A;
  22. protected BigInteger privB;
  23. protected BigInteger pubB;
  24. protected BigInteger u;
  25. protected BigInteger S;
  26. protected BigInteger M1;
  27. protected BigInteger M2;
  28. protected BigInteger Key;
  29. public Srp6Server()
  30. {
  31. }
  32. /**
  33. * Initialises the server to accept a new client authentication attempt
  34. * @param N The safe prime associated with the client's verifier
  35. * @param g The group parameter associated with the client's verifier
  36. * @param v The client's verifier
  37. * @param digest The digest algorithm associated with the client's verifier
  38. * @param random For key generation
  39. */
  40. public virtual void Init(BigInteger N, BigInteger g, BigInteger v, IDigest digest, SecureRandom random)
  41. {
  42. this.N = N;
  43. this.g = g;
  44. this.v = v;
  45. this.random = random;
  46. this.digest = digest;
  47. }
  48. public virtual void Init(Srp6GroupParameters group, BigInteger v, IDigest digest, SecureRandom random)
  49. {
  50. Init(group.N, group.G, v, digest, random);
  51. }
  52. /**
  53. * Generates the server's credentials that are to be sent to the client.
  54. * @return The server's public value to the client
  55. */
  56. public virtual BigInteger GenerateServerCredentials()
  57. {
  58. BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
  59. this.privB = SelectPrivateValue();
  60. this.pubB = k.Multiply(v).Mod(N).Add(g.ModPow(privB, N)).Mod(N);
  61. return pubB;
  62. }
  63. /**
  64. * Processes the client's credentials. If valid the shared secret is generated and returned.
  65. * @param clientA The client's credentials
  66. * @return A shared secret BigInteger
  67. * @throws CryptoException If client's credentials are invalid
  68. */
  69. public virtual BigInteger CalculateSecret(BigInteger clientA)
  70. {
  71. this.A = Srp6Utilities.ValidatePublicValue(N, clientA);
  72. this.u = Srp6Utilities.CalculateU(digest, N, A, pubB);
  73. this.S = CalculateS();
  74. return S;
  75. }
  76. protected virtual BigInteger SelectPrivateValue()
  77. {
  78. return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
  79. }
  80. private BigInteger CalculateS()
  81. {
  82. return v.ModPow(u, N).Multiply(A).Mod(N).ModPow(privB, N);
  83. }
  84. /**
  85. * Authenticates the received client evidence message M1 and saves it only if correct.
  86. * To be called after calculating the secret S.
  87. * @param M1: the client side generated evidence message
  88. * @return A boolean indicating if the client message M1 was the expected one.
  89. * @throws CryptoException
  90. */
  91. public virtual bool VerifyClientEvidenceMessage(BigInteger clientM1)
  92. {
  93. // Verify pre-requirements
  94. if (this.A == null || this.pubB == null || this.S == null)
  95. {
  96. throw new CryptoException("Impossible to compute and verify M1: " +
  97. "some data are missing from the previous operations (A,B,S)");
  98. }
  99. // Compute the own client evidence message 'M1'
  100. BigInteger computedM1 = Srp6Utilities.CalculateM1(digest, N, A, pubB, S);
  101. if (computedM1.Equals(clientM1))
  102. {
  103. this.M1 = clientM1;
  104. return true;
  105. }
  106. return false;
  107. }
  108. /**
  109. * Computes the server evidence message M2 using the previously verified values.
  110. * To be called after successfully verifying the client evidence message M1.
  111. * @return M2: the server side generated evidence message
  112. * @throws CryptoException
  113. */
  114. public virtual BigInteger CalculateServerEvidenceMessage()
  115. {
  116. // Verify pre-requirements
  117. if (this.A == null || this.M1 == null || this.S == null)
  118. {
  119. throw new CryptoException("Impossible to compute M2: " +
  120. "some data are missing from the previous operations (A,M1,S)");
  121. }
  122. // Compute the server evidence message 'M2'
  123. this.M2 = Srp6Utilities.CalculateM2(digest, N, A, M1, S);
  124. return M2;
  125. }
  126. /**
  127. * Computes the final session key as a result of the SRP successful mutual authentication
  128. * To be called after calculating the server evidence message M2.
  129. * @return Key: the mutual authenticated symmetric session key
  130. * @throws CryptoException
  131. */
  132. public virtual BigInteger CalculateSessionKey()
  133. {
  134. // Verify pre-requirements
  135. if (this.S == null || this.M1 == null || this.M2 == null)
  136. {
  137. throw new CryptoException("Impossible to compute Key: " +
  138. "some data are missing from the previous operations (S,M1,M2)");
  139. }
  140. this.Key = Srp6Utilities.CalculateKey(digest, N, S);
  141. return Key;
  142. }
  143. }
  144. }
  145. #pragma warning restore
  146. #endif