Tuesday, January 19, 2016

Sending an RSA encrypted message from client to Python socket server


The example below shows how to send an RSA encrypted message from a client to a Python socket server.

A Mac is used as the client, while a Raspberry Pi is used as the server. For the introduction to the Python socket server, refer to this:
Connect Mac / iPhone to a Simple Python Socket Server

Connection procedure of this example
1. Private and public keys generated in server.
2. Server enabled to listen to client.
3. Client sends "Client: OK" to server.
4. Server sends public key to client.
5. Client uses the public key to encrypt a message, which is then sent to server. 
6. Server decrypts the message and informs client "Server: OK".
7. Client tells the server to "Quit".
8. Both server and client are stopped.

Configurations for the server and client are as below:

Server (Raspberry Pi)

1. Install Python-Crypto.

sudo apt-get install python-crypto




2. Use sudo nano server_rsa.py command to edit a python file as below:

import socket
from Crypto.PublicKey import RSA
from Crypto import Random

#Generate private and public keys
random_generator = Random.new().read
private_key = RSA.generate(1024, random_generator)
public_key = private_key.publickey()

#Declartion
mysocket = socket.socket()
host = socket.gethostbyname(socket.getfqdn())
port = 7777
encrypt_str = "encrypted_message="

if host == "127.0.1.1":
    import commands
    host = commands.getoutput("hostname -I")
print "host = " + host

#Prevent socket.error: [Errno 98] Address already in use
mysocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

mysocket.bind((host, port))

mysocket.listen(5)

c, addr = mysocket.accept()

while True:

    #Wait until data is received.
    data = c.recv(1024)
    data = data.replace("\r\n", '') #remove new line character

    if data == "Client: OK":
        c.send("public_key=" + public_key.exportKey() + "\n")
        print "Public key sent to client."

    elif encrypt_str in data: #Reveive encrypted message and decrypt it.
        data = data.replace(encrypt_str, '')
        print "Received:\nEncrypted message = "+str(data)
        encrypted = eval(data)
        decrypted = private_key.decrypt(encrypted)
        c.send("Server: OK")
        print "Decrypted message = " + decrypted

    elif data == "Quit": break

#Server to stop
c.send("Server stopped\n")
print "Server stopped"
c.close()

Client (Mac)

1. Install Python-Crypto.

sudo easy_install pycrypto

2. Use sudo nano client_rsa.py command to edit a python file as below:

import socket
from Crypto.PublicKey import RSA

server = socket.socket()
host = "192.168.xx.xx"
port = 7777

server.connect((host, port))

#Tell server that connection is OK
server.sendall("Client: OK")

#Receive public key string from server
server_string = server.recv(1024)

#Remove extra characters
server_string = server_string.replace("public_key=", '')
server_string = server_string.replace("\r\n", '')

#Convert string to key
server_public_key = RSA.importKey(server_string)

#Encrypt message and send to server
message = "This is my secret message."
encrypted = server_public_key.encrypt(message, 32)
server.sendall("encrypted_message="+str(encrypted))

#Server's response
server_response = server.recv(1024)
server_response = server_response.replace("\r\n", '')
if server_response == "Server: OK":
    print "Server decrypted message successfully"

#Tell server to finish connection
server.sendall("Quit")
print(server.recv(1024)) #Quit server response
server.close()

Result

1. Type this command at the server:

python server_rsa.py

2. Type this command at the client:

python client_rsa.py

3. Result at the server:

host = 192.168.xx.xx 
Public key sent to client.
Received:
Encrypted message = ('\x9a\xe0\x08\xa1\xb6\x86?\xc7\xde\xb6\xa0\xbe\xa7!\xecem.\xb1R\xc5h\x19cv]{\xd3\x04\xcf\x0e\xf0\xfe\xc50\x1e\xc9U\xff\xd5\xf2\xb1,EQ\xdf2\x89![\xb7s\x84:C\xbdg\xbf$\x05\'\xb8@GK\x18Q\xd5N\xe9\x13\x12e\x8c\xe7F\xc8+\x95\xcdj\xb6\xcc9\xc8-t\x17-\xb8\xdei\x8f\x90\xdd\xcf\xd9@\xa0\xf8\xe8\xe5\xcci\xea"M\x82\xb8%\xf7\xfccc G{\x16A)\xf2\xcb"\x15\xa8\x16\xd3M',)
Decrypted message = This is my secret message.
Server stopped

4. Result at the client:

Server decrypted message successfully
Server stopped


References:

Connect Mac / iPhone to a Simple Python Socket Server
Encrypt / decrypt a string with RSA public / private keys in PHP
Encrypt / decrypt a string with RSA public / private PEM files using Python
Encrypt / decrypt a string with code-generated RSA public / private keys in Python

iOS:
Encrypt / decrypt a string with RSA public / private keys in Swift

9 comments:

  1. Perfect example, simple and straight forward. I am a newbie and I have one question.

    How do you build the server that handles many clients to that it processes data simultaneously by THREADING

    ReplyDelete
    Replies
    1. Good question! I'll study this when I have time.
      Here is one example, but I haven't tried it:

      http://www.techbeamers.com/python-tutorial-write-multithreaded-python-server/

      If this method works, please let me know. :)

      Delete
  2. Hello admin! When I try writing "python client_rsa.py" at the client side, I get this error:
    Traceback (most recent call last):
    File "client_rsa.py", line 8, in
    server.connect((host, port))
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 228, in meth
    return getattr(self._sock,name)(*args)
    socket.error: [Errno 60] Operation timed out

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  3. Hi, I have your code running great on both client and server.

    Is there a way to get the server to not shut down after 1 decode. i need it to stay up listening to new and old multiple connections.Also is it possible to write decoded output to a local file line by line , for raspberry pi.

    Thanks in advance

    ReplyDelete