Tutorial Five

 

Contents

 

Introduction

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

            Verifying a client

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

 

1.         Introduction

           

            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 sideIf 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.