SRP6Client.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 client 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 Srp6Client
  15. {
  16. protected BigInteger N;
  17. protected BigInteger g;
  18. protected BigInteger privA;
  19. protected BigInteger pubA;
  20. protected BigInteger B;
  21. protected BigInteger x;
  22. protected BigInteger u;
  23. protected BigInteger S;
  24. protected BigInteger M1;
  25. protected BigInteger M2;
  26. protected BigInteger Key;
  27. protected IDigest digest;
  28. protected SecureRandom random;
  29. public Srp6Client()
  30. {
  31. }
  32. /**
  33. * Initialises the client to begin new 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 digest The digest algorithm associated with the client's verifier
  37. * @param random For key generation
  38. */
  39. public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random)
  40. {
  41. this.N = N;
  42. this.g = g;
  43. this.digest = digest;
  44. this.random = random;
  45. }
  46. public virtual void Init(Srp6GroupParameters group, IDigest digest, SecureRandom random)
  47. {
  48. Init(group.N, group.G, digest, random);
  49. }
  50. /**
  51. * Generates client's credentials given the client's salt, identity and password
  52. * @param salt The salt used in the client's verifier.
  53. * @param identity The user's identity (eg. username)
  54. * @param password The user's password
  55. * @return Client's public value to send to server
  56. */
  57. public virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password)
  58. {
  59. this.x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
  60. this.privA = SelectPrivateValue();
  61. this.pubA = g.ModPow(privA, N);
  62. return pubA;
  63. }
  64. /**
  65. * Generates client's verification message given the server's credentials
  66. * @param serverB The server's credentials
  67. * @return Client's verification message for the server
  68. * @throws CryptoException If server's credentials are invalid
  69. */
  70. public virtual BigInteger CalculateSecret(BigInteger serverB)
  71. {
  72. this.B = Srp6Utilities.ValidatePublicValue(N, serverB);
  73. this.u = Srp6Utilities.CalculateU(digest, N, pubA, B);
  74. this.S = CalculateS();
  75. return S;
  76. }
  77. protected virtual BigInteger SelectPrivateValue()
  78. {
  79. return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
  80. }
  81. private BigInteger CalculateS()
  82. {
  83. BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
  84. BigInteger exp = u.Multiply(x).Add(privA);
  85. BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N);
  86. return B.Subtract(tmp).Mod(N).ModPow(exp, N);
  87. }
  88. /**
  89. * Computes the client evidence message M1 using the previously received values.
  90. * To be called after calculating the secret S.
  91. * @return M1: the client side generated evidence message
  92. * @throws CryptoException
  93. */
  94. public virtual BigInteger CalculateClientEvidenceMessage()
  95. {
  96. // Verify pre-requirements
  97. if (this.pubA == null || this.B == null || this.S == null)
  98. {
  99. throw new CryptoException("Impossible to compute M1: " +
  100. "some data are missing from the previous operations (A,B,S)");
  101. }
  102. // compute the client evidence message 'M1'
  103. this.M1 = Srp6Utilities.CalculateM1(digest, N, pubA, B, S);
  104. return M1;
  105. }
  106. /** Authenticates the server evidence message M2 received and saves it only if correct.
  107. * @param M2: the server side generated evidence message
  108. * @return A boolean indicating if the server message M2 was the expected one.
  109. * @throws CryptoException
  110. */
  111. public virtual bool VerifyServerEvidenceMessage(BigInteger serverM2)
  112. {
  113. // Verify pre-requirements
  114. if (this.pubA == null || this.M1 == null || this.S == null)
  115. {
  116. throw new CryptoException("Impossible to compute and verify M2: " +
  117. "some data are missing from the previous operations (A,M1,S)");
  118. }
  119. // Compute the own server evidence message 'M2'
  120. BigInteger computedM2 = Srp6Utilities.CalculateM2(digest, N, pubA, M1, S);
  121. if (computedM2.Equals(serverM2))
  122. {
  123. this.M2 = serverM2;
  124. return true;
  125. }
  126. return false;
  127. }
  128. /**
  129. * Computes the final session key as a result of the SRP successful mutual authentication
  130. * To be called after verifying the server evidence message M2.
  131. * @return Key: the mutually authenticated symmetric session key
  132. * @throws CryptoException
  133. */
  134. public virtual BigInteger CalculateSessionKey()
  135. {
  136. // Verify pre-requirements (here we enforce a previous calculation of M1 and M2)
  137. if (this.S == null || this.M1 == null || this.M2 == null)
  138. {
  139. throw new CryptoException("Impossible to compute Key: " +
  140. "some data are missing from the previous operations (S,M1,M2)");
  141. }
  142. this.Key = Srp6Utilities.CalculateKey(digest, N, S);
  143. return Key;
  144. }
  145. }
  146. }
  147. #pragma warning restore
  148. #endif