In the previous two, the design of the socket frame and the content of data transmission, the whole framework design guidelines are easy to use and good security, can be used from the client to the service side of the data security transmission, then achieve this goal needs to design good message transmission and data encryption processing. This article mainly describes how to use the socket Transfer Protocol to achieve data encryption and data integrity check processing, data encryption we can be based on the RSA asymmetric encryption method to achieve the integrity of the data, we can transmit the content of the MD5 data to verify the comparison.
1, the socket frame transmission content analysis
The protocol that describes the socket above, in addition to the start and end identifiers, is the entire content of a JSON string content, as shown in the following format.
In the above message, we can extract a complete socket message by starting the identity bit and ending the identity bit, so that we can get the corresponding entity class by serial number of the JSON content, we define the contents of the entity class as follows.
We divide the message object into the request message object and the reply message object, they correspond to requests and response messages, that is, one is the originating message, the other is the reply message. One of the "hosted JSON content is the JSON string of our other transfer object, so that we use this string to transfer information about different objects, we construct a common message entity object."
In addition, these transmitted message objects, which themselves can inherit from the base class of an entity class, so as to facilitate our uniform processing of them, as shown, is a generic message object Basemessage and the JSON content of the object diagram, such as Authrequest is a login authentication request, Authorrepsonse is the answer to the login verification.
Of course, our entire socket application can derive a lot of similar request and response message objects, as shown below is the definition of partial messages.
For asymmetric encryption processing, there are generally some performance losses, but we consider that if it is a secure environment of data transmission processing, we use asymmetric encryption is better.
Of course, some people recommend the use of asymmetric encryption part of the content, such as the use of the Convention symmetric encryption key, through asymmetric encryption to transfer the encryption key, and then the two sides using symmetric encryption algorithm to deal with is also possible. However, this framework mainly describes the use of asymmetric encryption to encrypt the JSON content, other parts of the general information is not encrypted.
2, asymmetric encryption of public key delivery
Before the transmission of the message encrypted data, we need to exchange the public key of the algorithm, that is, the server put its own public key to the client, the client receives the server's public key request, returns the client's public key to the server, realizes the exchange of both, and the message of both sides is encrypted by the public key The encrypted content is passed through the standard socket message object so that the encrypted content received by the other party can be decrypted by its own private key.
Then to handle this public key exchange before the message is delivered, we can design the server to send a new client connection (before the logon process), sending the server's public key to the client, the client receives the server's public key, responds to its public key information, and stores the server's public key. In this way, we can use the other public key to encrypt the data during the log-in and the subsequent message-passing process, and achieve better security.
The process of public key delivery is shown, that is, after the client initiates a connection server request, the server actively sends a public key request command, the client receives the response, sends its own public key to the server, and the server stores the client's public key information on the corresponding socket object. All messages are later encrypted with the client public key and then sent to the client.
As we have described earlier, all of our custom socket objects are inherited from a base class object such as Basesocketclient, then we only need to add a few properties to its object, one is its own public key, the private key, and the other's public key information, as shown below.
After the start of the program, including the client startup, the server starts, we need to build their own public key information, the following code is to generate the corresponding public key private key information, and stored in the attribute.
using New RSACryptoServiceProvider ()) { this. Rsapublickey = RSA. Toxmlstring (false); // Public Key this. Rsaprivatekey = RSA. Toxmlstring (true); // private key }
For example, on the server side, after the client socket is successfully connected, we send a public key request message to the corresponding client, as shown in the following code.
/// <summary> ///processing after a client is connected (such as sending a public key key)/// </summary> /// <param name= "Client" >Connecting Clients</param> protected Override voidonafterclientconnected (Clientofshop client) {//the public key of the server is logged first, the private keyClient. Rsaprivatekey =Portal.gc.RSAPrivateKey; Client. Rsapublickey=Portal.gc.RSAPublicKey; //send a Public key exchange command varRequest =Newrsakeyrequest (Portal.gc.RSAPublicKey); vardata =request. Packdata (); Client. SendData (data); Thread.Sleep ( -); }
Then on the client, after receiving the service side of the message, to determine the message type, if it is a public key request, then we need to respond, the public key to the server, or else to do other business processing.
/// <summary> ///overriding the processing of read messages/// </summary> /// <param name= "message" >Gets the complete socket message Object</param> protected Override voidonmessagereceived (Basemessage message) {if(Message. Msgtype = =datatypekey.rsarequest) {varinfo = jsontools.deserializeobject<rsakeyrequest>(message. Content); if(Info! =NULL) { //record the other's public key into the socket object This. Peerrsapublickey = Portal.gc.UseRSAEncrypt? Info. Rsapublickey:""; Console.WriteLine ("using RAS encryption: {0}, gets the encrypted public key to: {1}", Portal.gc.UseRSAEncrypt, info. Rsapublickey); //Public key Request reply varPublicKey = Portal.gc.UseRSAEncrypt? Portal.gc.RSAPublicKey:""; vardata =NewRsakeyresponse (PublicKey);//returns the client's public key varmsg =data. Packdata (message); SendData (msg); Thread.Sleep ( -);//Pause under } } Else { //handing over to the business message processing process This. Messagereceiver.appendmessage (message); This. Messagereceiver.check (); } }
If our exchange succeeds, our subsequent messages can be processed by RSA asymmetric encryption, as shown in the following code.
Data. Content = Rsasecurityhelper.rsaencrypt (this. Peerrsapublickey, data. Content);
Decrypting the message is the inverse of the code above, as shown below.
Message. Content = Rsasecurityhelper.rsadecrypt (this. Rsaprivatekey, message. Content);
Finally, we make the encrypted content a socket message to be sent, containing the start and end identifiers, as shown below.
// Convert to JSON and assemble to send protocol format var json = jsontools.objecttojson (data); string. Format ("{0}{1}{2}", (char)this. Startbyte, JSON, (char)this. Endbyte);
This is what we need to send the message content, we intercept the content, you can see the contents are as follows.
Above the contents of the red box, you must use the original private key to decrypt, that is, on the network, who intercepted, can not be untied, to ensure the security of the data.
3. Data integrity Check
The integrity of the data, we can use the message content of the MD5 value of the comparison, implementation checks whether the content has been tampered with, but if the use of asymmetric encryption, this integrity check can be ignored, but we can keep it as a check processing.
Therefore, when the data is encapsulated, the content portion of the MD5 value is computed, as shown below.
Data. MD5 = md5util.getmd5_32 (data. Content); // gets the MD5 value of the content
Then, after obtaining the message and decrypting it (if any), calculate the MD5 value on the server side and compare it with the MD5 value passed, if the agreement is not tampered with, as shown in the following code.
var md5 = md5util.getmd5_32 (message. Content); if (MD5 = = message. MD5) { onmessagereceived (message); // to overload a child class } else { log.writeinfo (string. Format (" received a modified message: \r\n{0}", message. Content)); }
This is what I do in the socket development framework, the implementation of asymmetric encryption of transmission data, as well as data integrity check processing process.
Data encryption and integrity checking of the socket development framework