/// <summary> /// Try to login with the auth server. /// </summary> /// <param name="email">Username</param> /// <param name="password">Password</param> public void TryLogin(string email, string password) { //If we haven't already started trying to login... if (_loginThread != null && _loginThread.ThreadState != ThreadState.Stopped) { return; } try { var stateInfo = new AuthStateInfo(this, new AuthParams(email, password)); _loginThread = new Thread(TryLogin); _loginThread.Start(stateInfo); } catch (Exception e) { _logging.LogException("Authentication", e, "TryLogin", "Caught exception starting login process:"); } }
/// <summary> /// Do the Login process. /// </summary> /// <param name="authStateInfo">Reference to an AuthStateInfo instance containing login info</param> private void Login(AuthStateInfo authStateInfo) { //Used as the y value in key calculations BigInteger randomBigInteger = null; //Used as the client public key (v) for the server to derive the secret key with BigInteger clientPublicKey = null; //Calculated secret key used for encryption BigInteger sessionKey = null; //The caluclations have a nasty habit of giving non-64-byte numbers, so re-calculate as //necessary 'til they're all 64-bytes long while ((object)randomBigInteger == null || randomBigInteger.ToHexString().Length != 64 || ((object)clientPublicKey == null || clientPublicKey.ToHexString().Length != 64) || ((object)sessionKey == null || sessionKey.ToHexString().Length != 64)) { randomBigInteger = GetRandomBigInteger(_modulus); //v = g^y mod p clientPublicKey = _generator.modPow(randomBigInteger, _modulus); //secret key = [server public key]^y mod p sessionKey = _serverPublicKey.modPow(randomBigInteger, _modulus); } //Create the userInfoString which will be encrypted and transmitted to the auth server var userInfoString = string.Format("{0} {1}", authStateInfo.AuthParams.Username, authStateInfo.AuthParams.Password); //Get a byte[] representing the userInfoString var userInfoBytes = Encoding.ASCII.GetBytes(userInfoString); // Key and iv for encryption // Key is the sessionKey in Hex string key = sessionKey.ToHexString(); // iv is the string iv = _modulus.ToHexString().Substring(0, 32); //Get the encrypted user info bytes using our key and IV var encryptedUserInfoBytes = EncryptBytes(userInfoBytes, key, iv); //Get the byte[] for our hardware hash var hardwareHashBytes = GenerateHardwareHash(); //Get the encrypted bytes for the hardware hash var encryptedHardwareHashBytes = EncryptBytes(hardwareHashBytes, key, iv); //Convert the encrypted byte[]s into Base64-strings, then url-encode them string encryptedHardwareHashString = System.Web.HttpUtility.UrlEncode( Convert.ToBase64String(encryptedHardwareHashBytes)), encryptedUserInfoString = System.Web.HttpUtility.UrlEncode( Convert.ToBase64String(encryptedUserInfoBytes)); //Get the hex string of the public key var clientPublicKeyString = clientPublicKey.ToHexString(); //Try to authenticate with each auth server until we have a successful one. foreach (var serverUrl in AUTH_SERVERS) { var formattedUrl = string.Format("{0}?a={1}&b={2}&c={3}", serverUrl, clientPublicKeyString, encryptedUserInfoString, encryptedHardwareHashString); _logging.LogMessage("Authentication", "Authenticate", LogSeverityTypes.Debug, "Request URL: {0}", formattedUrl); //Try to authenticate and save the result var authResult = Authenticate(formattedUrl, key, iv); //Firstly, if it was bad response, just re-try. if (authResult.AuthenticationResult == ERROR_BAD_RESPONSE) { authResult = Authenticate(formattedUrl, key, iv); } //If the connection succeeded... if (authResult.DidAuthenticationFail) { //Fire the event with the login result. if (AuthenticationComplete != null) { AuthenticationComplete(authResult, authResult); } //We're done with auth; return return; } } //If we didn't successfully connect, fire event with an auth result stating so. _logging.LogMessage("Authentication", "Login", LogSeverityTypes.Debug, "Last chance return"); var loginResult = new __err_retn(false, ERROR_UNKNOWN, false); if (AuthenticationComplete != null) { AuthenticationComplete(loginResult, loginResult); } }