PDA

View Full Version : [Fixed in ES 5.3] Enabling encryption changes hash IDs?



CrimsonShadow
02-27-2011, 11:56 PM
I'm trying to do an encrypted login with some custom hashing of passwords and such but it seems like if I turn on encryption the hashId value on the client no longer matches the server side and the login is rejected as a result. I was able to reproduce the same behavior by modifying the LoginPasswordHashing example to change the client to enable encryption and wait for the encryption changed event before showing the login dialog. (Code copied below.)

Is this the intended behavior? Do I need to do something on the server side to compensate for an encrypted connection?

Thanks.


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="onCreationComplete();" >

<mx:Script>
<![CDATA[

//ElectroServer imports
import com.electrotank.electroserver5.ElectroServer;

//ElectroServer message objects
import com.electrotank.electroserver5.api.ConnectionRespo nse;
import com.electrotank.electroserver5.api.LoginRequest;
import com.electrotank.electroserver5.api.LoginResponse;
import com.electrotank.electroserver5.api.MessageType;
import com.electrotank.electroserver5.api.EncryptionState ChangeEvent;

//For hashing the password
import com.electrotank.electroserver5.util.CryptoTools;

//Logger imports
import com.electrotank.electroserver5.util.ES5TraceAdapte r;
import com.electrotank.logging.adapter.Log;
import com.electrotank.logging.adapter.ILogger;

//Flash imports
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;

//add this so we can see the logs get traced
Log.setLogAdapter(new ES5TraceAdapter());

private var _es:ElectroServer = new ElectroServer();
private var _hashId:int = 0;

private function onCreationComplete():void {

//remove the visual pieces we don't need yet
removeChild(loginPanel);

//load the connection settings, and connect
_es.loadAndConnect("settings.xml");

//listen for certain events to allow the application to flow, and to support chatting and user list updates
_es.engine.addEventListener(MessageType.Connection Response.name, onConnectionResponse);
_es.engine.addEventListener(MessageType.LoginRespo nse.name, onLoginResponse);
_es.engine.addEventListener(MessageType.Encryption StateChange.name, onEncryptionStateChangeResponse);
}

/**
* Fired when a connection to the server has either succeeded or failed.
*/
private function onConnectionResponse(e:ConnectionResponse):void {
if (e.successful) {
_hashId = e.hashId;
trace("Connection hashId: " + _hashId);
_es.engine.setEncryptionEnabled(true);
} else {
waitingField.text = "Connection failed!";
}
}

private function onEncryptionStateChangeResponse(event:EncryptionSt ateChangeEvent):void
{
//add the login panel so the user can login
removeChild(waitingPanel);
addChild(loginPanel);
}

/**
* Fired after the client has sent a login request, and the server has responded.
*/
private function onLoginResponse(e:LoginResponse):void {
if (e.successful) {

waitingField.text = "Logged in!";
} else {
waitingField.text = "Login failed!";
}
}

/**
* Called when the user clicks the 'submit' button on the login panel
*/
private function submitClicked():void {

//create a LoginRequest, and send it
var lr:LoginRequest = new LoginRequest();
lr.userName = userNameField.text;

lr.password = new CryptoTools().generatePasswordHash(passwordField.t ext, _hashId);
trace("LoginRequest: " + userNameField.text + ", " + _hashId + ", " + lr.password);

//Note: we do not set the hashId in the LoginRequest. That is done automatically.

_es.engine.send(lr);

removeChild(loginPanel);
addChild(waitingPanel);
}



]]>
</mx:Script>

<mx:Panel id="waitingPanel">
<mx:Text text="Please wait..." id="waitingField" />
</mx:Panel>

<mx:Panel title="Log in" id="loginPanel">
<mx:Form width="100%" height="100%">
<mx:FormItem label="User name" width="100%">
<mx:TextInput id="userNameField" width="100" />
</mx:FormItem>
<mx:FormItem label="Password" width="100%">
<mx:TextInput id="passwordField" width="100" />
</mx:FormItem>
</mx:Form>
<mx:ControlBar>
<mx:Button label="Submit" enabled="{userNameField.text.length > 0}" click="submitClicked();" />
</mx:ControlBar>
</mx:Panel>


</mx:Application>

tcarr
02-28-2011, 12:46 AM
I don't think I've tried doing hashed login over an encrypted channel. I'll try to reproduce it tomorrow.

tcarr
02-28-2011, 05:08 PM
I've reproduced the error. This is not expected behavior. I'll add the bug to our tracking system. In the meantime, if you want to use password hashing AND encryption, try enabling the encryption when the login response returns instead of before.

CrimsonShadow
03-01-2011, 04:40 AM
Thank you Teresa. I'll follow your suggested work around for now.

tcarr
03-01-2011, 09:39 AM
I just thought of a possibly better workaround. Store the hashId that you use (which can be a random one even) in the optional EsObject on the LoginRequest. Then you will need to unpack that EsObject in your LoginEventHandler, and use that hashId to to hash the database's password, then compare. You might try doing setPasswordHash on the LoginContext and then using the built in password hash comparison. I'm not sure that will work. Offered as a second option.

tcarr
08-24-2011, 03:50 PM
This is fixed for ES5.3 (not yet released).