Tutorial Five
Contents
Analyze business security
requirements with simple sample
Steps for securing required requests
and return results with BlowFish
Description of SocketPro
security protocol
Calling IUSocket::SwitchTo without password
Hashing a password with a unique salt on server side
Authenticating a remote SocketPro server
When should we use the protocol?
Selectively securing a few requests and return results for
better performance and scalability
Simplification of security settings
Don’t want to exchange password between client
and server
One flaw of SocketPro security
protocol
Securing data communications between two machines is not a trivial work. We spend a lot of time to make our SocketPro as secure as possible. SocketPro fully supports industrial standard security protocol SSL/TLS to ensure data exchanging security, as shown in the previous tutorial two and other samples. However, we don’t think the industrial standard SSL/TLS is perfect under all of cases. It has three major flaws, complexity, certificate settings and low performance for handshaking and securing all of transferred data. Long time ago, we planned to develop a new security protocol for our SocketPro so that both client and server applications are able to selectively encrypt the requests and results that are just required by business. Now, we have a protocol to secure just-needed requests and return results with zero security settings and super simplicity, which may lead to better security.
Our SocketPro security protocol is simply rooted on hashing password with salt to create a private key on the fly for BlowFish. As long as you understand hash and BlowFish, you will have no problem in understanding the simple security protocol.
2. Analyze business security requirements with simple sample
First of all, forget theories about encryption. Let’s concentrate on the below universal interface definition file MyBlowFish.uid.
[
ServiceID = 101 //service id can't be less than 0
]
CMySecure
{
//Secured
$string Open(in string
strUserIDToDB, in string strPasswordToDB);
bool BeginTrans();
$bool ExecuteNoQuery(in string
strSQL);
bool
Commit(in bool bSmart);
}
Calling the first method Open
requires sending a user id and his or her password to a remote SocketPro server
so that this request must be secured. All of other methods will not cause
transferring any sensitive data at all. Therefore, the other three methods are
not required to be secure. Additionally, all of requests will not return any
sensitive data either. So we’ll not secure any return results. Keep the above
requirements in mind. We use uidparser.exe to create base code for both client
and server, as described in the tutorial one.
3. Steps for securing
required requests and return results with BlowFish
On server side, we need to set
encryption method to BlowFish like we did for SSL/TLS, as shown in the below
code before starting listening socket on a port.
AuthenticationMethod = tagAuthenticationMethod.amOwn;
DefaultEncryptionMethod = tagEncryptionMethod.BlowFish;
Note that you must set authentication method to amOwn as shown in the above. Otherwise, it does not make sense in logical as you understand the coming sections.
On client side, you have to set
encryption method to BlowFish before calling CClientSocket::SwitchTo when a
socket connection is established as shown in the below code.
private void
OnConnected(int nSocketHandle, int nError)
{
if (nError == 0)
{
btnToDB.Enabled = true;
m_ClientSocket.EncryptionMethod = tagEncryptionMethod.BlowFish;
//set user id and
password
m_ClientSocket.SetUID(txtUserID.Text);
m_ClientSocket.SetPassword(txtPassword.Text);
//switch for the
service identified by m_AsynHandler
m_ClientSocket.SwitchTo(m_AsynHandler);
//password cleaned right after SwitchTo is returned
internally
}
else
{
MessageBox.Show(m_ClientSocket.GetErrorMsg());
}
}
In addition to setting encryption
method, it is also recommended that you set password right before calling
CClientSocket::SwitchTo. By this way, password can be cleaned right after the
method SwitchTo returns so that it leads to better security.
Additionally, you have to use the
below code to set a password by calling static method CBaseService::SetPassword
on server side inside the virtual function CSocketProServer::OnIsPermitted.
protected override bool
OnIsPermitted(int hSocket, int nSvsID)
{
string strUserID = CBaseService.GetUserID(hSocket);
string strPassword = GetPasswordFromStore(strUserID);
//set password so that the hash of the password with salt
can be sent to a client for authentication on client side.
CBaseService.SetPassword(hSocket,
strPassword);
return
true;
}
Pay attention to the above comment.
Contrary to SSL/TLS and others, authentication actually happens on client side with
our secure protocol! The second speciality is that we set password on both
client and server side, but password is never transferred across machines. Wait
for a moment until the coming section for detailed description.
Once authentication is completed on
client side and be verified on server side, BlowFish objects on both client and
server sides are automatically created with one private key. The private key is
dependent on a password and a session key (salt for hash). Because the session
key always changes from connection to connection, the corresponding private key
always varies from connection to connection. The private key is unique for each
of socket connections.
On server side, we use the below
code to disable encryption because we don’t need to encrypt any return results
as described in the above section.
protected override void OnSwitchFrom(int
nServiceID)
{
//All return results are not required to be secure
EncryptionMethod
= tagEncryptionMethod.NoEncryption;
}
On client side, we encrypt the
method Open request as below.
private void
btnToDB_Click(object sender, EventArgs e)
{
USocketClass usc = m_ClientSocket.GetUSocket();
//we like to encrypt data before sending the request to
server
usc.EncryptionMethod
= (short)USOCKETLib.tagEncryptionMethod.BlowFish;
if (m_AsynHandler.Open(txtUserID.Text,
txtPassword.Text) == null)
MessageBox.Show(m_AsynHandler.m_strErrorMessage);
else
btnExecuteSQL.Enabled = true;
}
Also, we disable encryption for
other methods as shown in the below code.
private void
btnExecuteSQL_Click(object sender, EventArgs e)
{
USocketClass usc = m_ClientSocket.GetUSocket();
//we do not want to encrypt data for the below requests
usc.EncryptionMethod
= (short)USOCKETLib.tagEncryptionMethod.NoEncryption;
m_ClientSocket.BeginBatching();
m_AsynHandler.BeginTransAsyn();
m_AsynHandler.ExecuteNoQueryAsyn(txtSQL.Text);
m_AsynHandler.CommitAsyn(true);
m_ClientSocket.Commit(true);
m_ClientSocket.WaitAll();
}
If you don’t understand the above
codes, please have a look at tutorial one. As you can see, the code is very
simple but truly secure. Now, let’s move onto the next section for describing
our secure protocol.
4. Description of SocketPro
security protocol
Our SocketPro security protocol is
rooted on hashing a password with a unique salt for each of socket connections.
Authentication happens on client side first and not on server side. Password is
never transferred on wire. Password is set for purely creating hash only.
Calling
CClientSocket::SwitchTo without sending password -- After a socket
connection is established, a client calls CClientSocket::SwitchTo and just
sends a user id only without sending password. This is the initial step of
handshaking. Afterwards, the client waits for a hash value and salt from a
connected server.
Hashing
a password with a unique salt on server side
– Once a SocketPro server receives the above key request, inside the virtual
function CSocketPro::OnIsPermitted, we get a password from a secured store and
set it into SocketPro so that SocketPro will use a specific function (1st
function) to hash a password with a unique salt for each of socket connections.
Afterwards, SocketPro will return the hash value and the unique salt back to
the client. Also, we use a new function (2nd function) to create a
private key for BlowFish using a hash value of the password with the same salt.
At last, we clean the input password and don’t use it any more. However,
SocketPro records the salt value.
Authenticating
a remote SocketPro server – Once the client receives
the return result, SocketPro will use the input password and obtained salt from
server to get a hash value with the 1st function. SocketPro compares
the calculated hash with the hash returned from SocketPro server inside
usocket.dll. If two hash values equal to each other, we’ll continue the next
step. Otherwise, the socket connection is immediately closed with error code (9
or tagSocketError.seClientAuthenticationError).
The first step is over
here.
Verifying a client on server side – If the above step is successful, inside usocket.dll SocketPro will use the 2nd function to get a new hash value (password + salt) as SocketPro server does. A BlowFish is created internally with the hash value as private key. As you can see, the private keys on client and server sides are equal to each other. At the moment, we clean the input password and don’t need any more. Now, on client side SocketPro will automatically encrypt the salt originated from server and send it back to server (tagBaseRequestID.idVerifySalt). Once server gets the encrypted data and decrypts it back to salt, SocketPro server will verify the decrypted salt with originally recorded salt (See step 1). If two salts are equal to each other, the whole handshake is successful and a client is now able to do whatever the client likes. Otherwise, the socket connection immediately closed with error code (261 or ERROR_VERIFY_SALT). The second step is over here.
SocketPro server will not turn off socket connection when a client calls SwithTo without giving a password for BlowFish encryption, but it is very alert to the base request idVerifySalt. If anything is not expected or calls do not follow the above procedures, SocketPro server will disconnect a client. At this time, we use SHA-1 for calculating the hash values. The salt is simply a GUID generated from window system function CoCreateGuid. The private key for BlowFish is 160 bit (20 bytes) in length. Our SocketPro framework is very extensible. If required, we can change hash functions and others in the future releases. We may support negotiating other symmetrical encryption methods on both client and server sides in the future.
As you can see, the input password has a key role in our SocketPro security protocol. Authentication happens first on client side instead of server side, but server also verifies if a client truly has an expected password for a user id. In comparison to SSL/TLS, you don’t need any certificates at all with SocketPro security protocol. Certificates make SSL/TLS difficult to understand and set up for a common software user.
5. When should we use the protocol?
As long as you understand our design purpose of this security protocol, you may have already known answers for this question.
Selectively securing a few requests and return results for better performance and scalability -- If you want to selectively secure a few key requests or return results, you should use this protocol for saving CPU rate so that you have a faster distributed application system to support more socket connections. Also, handshake of this simple protocol is simpler and faster than SSL/TLS without transferring any certificates at all.
Simplification of security settings -- If you like to build a distributed system with much less security settings and make a common user less frustrated with complex security setting, you should use this simple protocol instead of SSL/TLS. SSL/TLS is secure and robust in theory, but practically it is not that secure, because a common user does not really understand it so that certificates on both client and server sides can be possibly changed by bad hackers without knowing. SocketPro secure protocol does not have such a problem at all. Further, this simple security protocol is especially great for main-in-middle attack. There is no security hole for man-in-middle attack with this simple protocol. In addition, commercial certificates are pretty expensive because you have to pay a license fee every a few years. Therefore, SocketPro secure protocol may save money for you.
Don’t want to exchange password between client and server -- Our SocketPro secure protocol does not exchange password between client and server at all. This feature may lead you to use this simple protocol.
6. One flaw of SocketPro secure protocol
One known problem is that you can’t integrate this protocol with your enterprise or other security systems. This is the reason that you have to use amOwn for your authentication method on server side as shown in this tutorial. You have to create your own secured user id and password store protected by master password. However, features of zero security setting, speed and no certificates may largely offset this flaw.