[Twisted-Python] Re: How to make a secure connection between two computers

Noam Raphael noamraph at gmail.com
Tue Feb 12 15:02:00 EST 2008


Thanks all!

I think that at the end, I'll just use Python's plain socket, since I
don't intend to serve more than one request at a time. I also don't
really need to use SSL, since my two computers can have a pre-shared
secret. Here's what I wrote - tell me what you think!

#!/usr/bin/env python

import sys
import socket

from Crypto.Hash import SHA
from Crypto.Cipher import ARC4

RANDOM_LEN = 16

def get_random():
    return open('/dev/urandom').read(RANDOM_LEN)

def recv(sock, n):
    buf = ''
    while len(buf) < n:
        r = sock.recv(n - len(buf))
        if not r:
            raise socket.error("Couldn't read enough bytes")
        buf += r
    return buf

def handshake(sock, secret):
    my_random = get_random()
    my_rc4 = ARC4.new(SHA.new(secret + my_random).digest())
    sock.sendall(my_random)
    peer_random = recv(sock, RANDOM_LEN)
    peer_rc4 = ARC4.new(SHA.new(secret + peer_random).digest())
    sock.sendall(peer_rc4.encrypt('\0'*RANDOM_LEN))
    peer_response = recv(sock, RANDOM_LEN)
    if my_rc4.decrypt(peer_response) != '\0' * RANDOM_LEN:
        raise socket.error('Failed peer authentication')
    return my_rc4, peer_rc4

def server(host, port, secret):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((host, port))
    s.listen(1)
    while True:
        conn, addr = s.accept()
        print 'Connected by', addr
        conn.settimeout(1)
        try:
            my_rc4, peer_rc4 = handshake(conn, secret)
            while True:
                data = my_rc4.decrypt(conn.recv(1024))
                if not data: break
                print 'Received', repr(data)
                conn.send(peer_rc4.encrypt(data))
            conn.close()
        except socket.error, e:
            print 'Error:', e
        else:
            print 'Closed connection'

def client(host, port, secret):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)
    s.connect((host, port))
    my_rc4, peer_rc4 = handshake(s, secret)
    s.send(peer_rc4.encrypt('Hello, world'))
    data = my_rc4.decrypt(s.recv(1024))
    s.close()
    print 'Received', repr(data)

def main():
    if len(sys.argv) != 5 or sys.argv[1] not in ('server', 'client'):
        print "Usage: %s server/client host port secret"
        return
    is_server = sys.argv[1] == 'server'
    host = sys.argv[2]
    port = int(sys.argv[3])
    secret = sys.argv[4]
    if is_server:
        server(host, port, secret)
    else:
        client(host, port, secret)

if __name__ == '__main__':
    main()




More information about the Twisted-Python mailing list