/test/server.py
https://bitbucket.org/kewegmey/zmessage · Python · 134 lines · 76 code · 19 blank · 39 comment · 16 complexity · 1aebf14e09f009922a07c68cc699f8ad MD5 · raw file
- import zmq.auth
- from zmq.auth.thread import ThreadAuthenticator
- import os
- import logging
- import rsa
- import binascii
- import json
- import uuid
- def process_incoming(msg):
- # message should be a dict representing the json sent
- # the type field specifies what kind of message this is
- if msg['type'] == 'regular_msg':
- # This is a chat message destined for a user
- # Call reg_message handler
- return regular_msg(msg)
- elif msg['type'] == 'msg_recv':
- # This is a client asking for message delivery
- # Don't call anything. For now user will just poll for new messages.
- print "Not ready"
- elif msg['type'] == 'usr_reg':
- # User is trying to register their username and public key combo
- # Call usr_reg handler
- return usr_reg(msg)
- elif msg['type'] == 'key_lookup':
- # User wants to lookup another user's pubkey
- # Call key_lookup handler
- return key_lookup(msg)
- elif msg['type'] == 'msg_query':
- # User is asking if they have any messages
- # Call msg_query
- print "Not ready"
- def regular_msg(msg):
- # Process chat message destined for user
- # Double check that message is reg_msg
- if msg['type'] == 'regular_msg':
- # Accept message and save in queue
- # queue will be a dict msgs[destpubkey][messageid][actualmessageobj]
- return {"status": "Message sent."}
-
- def msg_recv(msg):
- # Process client request for message in queue.
- # Double check that message is msg_recv
- if msg['type'] == 'msg_recv':
- # Notification of waiting message will have been recvd by dest. Dest client will have sent REQ with signed message including the id for the requested message.
- # First verify the msg_recv came from the same key as the reg_msg's dest. (ensure the requesting client is the proper recipient)
- # reply to client with message if signature checks out.
- print "Not ready"
- def usr_reg(msg):
- #global pubkeys
- # user is trying to register username/pubkey
- if msg['type'] == 'usr_reg':
- # Grab the user's public key from from user_kvp and verify that user_kvp came from the associated privkey
- pubkeyo = rsa.PublicKey(5,3)
- srcpubkey = pubkeyo.load_pkcs1(msg['message']['pubkey'], format='PEM')
- try:
- print "Verifying Message"
- ser_msg = json.dumps(msg['message'])
- if rsa.verify(ser_msg, binascii.unhexlify(msg['signature']), srcpubkey):
- print "Message authentic!"
- username = msg['message']['username']
- pubkeys[username] = srcpubkey
- return {"status": "Successfully registered."}
- except:
- print "Verification Failed"
- return {"status": "Failed to register. Unable to verify signature"}
- # if it does then add key-value pair to key registry
- def key_lookup(msg):
- #global pubkeys
- # User is looking up another users Key
- if msg['type'] == 'key_lookup':
- # No need to verify signatures on the recv side since these are public however we should sign the message back to the user so that they can sort of trust the key is correct.abs
- # Lookup pubkey for specified user and then sign a message with that key back to requester.
- username = msg['message']
- if username in pubkeys:
- pubkey = pubkeys[username]
- pubkey = pubkey.save_pkcs1('PEM')
- return {username: pubkey}
- else:
- return {"status": "User not found"}
-
- def msg_query(msg):
- if msg['type'] == 'msg_query':
- # Verify user and then look for any messages for that key
- # reply with any messages
- print "Not ready"
- def main():
- # Main function sets up ZMQ server and waits for messages
- auth_keys = "keys/authkeys"
- # Start child threads
- public_keys_dir = os.path.abspath(auth_keys)
- ctx = zmq.Context.instance()
- # Start an authenticator for this context.
- auth = ThreadAuthenticator(ctx, log=logging)
- auth.start()
- # Tell authenticator to use the certificate in a directory
- auth.configure_curve(domain='*', location=public_keys_dir)
- server = ctx.socket(zmq.REP)
- server_secret_file = os.path.abspath("keys/server.key_secret")
- server_public, server_secret = zmq.auth.load_certificate(server_secret_file)
- server.curve_secretkey = server_secret
- server.curve_publickey = server_public
- server.curve_server = True # must come before bind
- server.bind("tcp://*:5555")
- print "Starting Server"
- # Message loop
- while True:
- # Block for message.
- message = server.recv_json()
- print "Received request: ", message
- # Call processor
- reply = process_incoming(message)
- server.send_json(reply)
- # Create pubkeys dict that will map usernames to public keys
- pubkeys = {}
- msg_queue = {}
- if __name__ == "__main__":
- main()