summary refs log tree commit diff
path: root/Crypto/src/crypto/agreement/srp/SRP6Client.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/agreement/srp/SRP6Client.cs')
-rw-r--r--Crypto/src/crypto/agreement/srp/SRP6Client.cs93
1 files changed, 93 insertions, 0 deletions
diff --git a/Crypto/src/crypto/agreement/srp/SRP6Client.cs b/Crypto/src/crypto/agreement/srp/SRP6Client.cs
new file mode 100644

index 000000000..309736564 --- /dev/null +++ b/Crypto/src/crypto/agreement/srp/SRP6Client.cs
@@ -0,0 +1,93 @@ +using System; + +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Agreement.Srp +{ + /** + * Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe. + * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper + * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002" + */ + public class Srp6Client + { + protected BigInteger N; + protected BigInteger g; + + protected BigInteger privA; + protected BigInteger pubA; + + protected BigInteger B; + + protected BigInteger x; + protected BigInteger u; + protected BigInteger S; + + protected IDigest digest; + protected SecureRandom random; + + public Srp6Client() + { + } + + /** + * Initialises the client to begin new authentication attempt + * @param N The safe prime associated with the client's verifier + * @param g The group parameter associated with the client's verifier + * @param digest The digest algorithm associated with the client's verifier + * @param random For key generation + */ + public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random) + { + this.N = N; + this.g = g; + this.digest = digest; + this.random = random; + } + + /** + * Generates client's credentials given the client's salt, identity and password + * @param salt The salt used in the client's verifier. + * @param identity The user's identity (eg. username) + * @param password The user's password + * @return Client's public value to send to server + */ + public virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password) + { + this.x = Srp6Utilities.CalculateX(digest, N, salt, identity, password); + this.privA = SelectPrivateValue(); + this.pubA = g.ModPow(privA, N); + + return pubA; + } + + /** + * Generates client's verification message given the server's credentials + * @param serverB The server's credentials + * @return Client's verification message for the server + * @throws CryptoException If server's credentials are invalid + */ + public virtual BigInteger CalculateSecret(BigInteger serverB) + { + this.B = Srp6Utilities.ValidatePublicValue(N, serverB); + this.u = Srp6Utilities.CalculateU(digest, N, pubA, B); + this.S = CalculateS(); + + return S; + } + + protected virtual BigInteger SelectPrivateValue() + { + return Srp6Utilities.GeneratePrivateValue(digest, N, g, random); + } + + private BigInteger CalculateS() + { + BigInteger k = Srp6Utilities.CalculateK(digest, N, g); + BigInteger exp = u.Multiply(x).Add(privA); + BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N); + return B.Subtract(tmp).Mod(N).ModPow(exp, N); + } + } +}