1. Ivan Vučica
  2. Pythia

Commits

Ivan Vučica  committed e1f43ca

Functional reading of login data. Added XTEA module. Added building an outgoing network message. Making use of Adler32 checksum from zlib. Attempted to add encryption using XTEA module, but something goes wrong.

  • Participants
  • Parent commits 47c61e2
  • Branches default

Comments (0)

Files changed (2)

File server.py

View file
 #                    #
 ######################
 
+from rsa import rsa
 import socket,threading
-from rsa import rsa
+import xtea
+import zlib
 
 class Server:
 	""" 
 
 class NetworkMessage:
 	def __init__(self):
-		pass
+		self.msg = ""
 	def fetchMessage(self, sock):
 		msgsz = sock.recv(2)
 		if len(msgsz)==1: msgsz += sock.recv(1)
 			self.msg += sock.recv(msgsz - len(self.msg))
 			print "Remaining " + str(msgsz - len(self.msg)) + " bytes"
 
+	def readCharacters(self, n):
+		r = self.msg[:n]
+		self.msg = self.msg[n:]
+		return r
 	def readU8(self):
 		r = ord(self.msg[0])
 		self.msg = self.msg[1:]
 		r1 = self.readU16()
 		r2 = self.readU16()
 		return r1 + r2*256*256
-
+	def readString(self):
+		n = self.readU16()
+		return self.readCharacters(n)
+	##
+	def sendMessage(self, sock):
+		# prefix with message size
+		size = len(self.msg)
+		size = chr(size & 0x00FF) + chr((size & 0xFF00) >> 8)
+		sock.send(size)
+		# send message
+		sock.send(self.msg)
+		print len(self.msg)
+		print size[0] + "." + size[1] + " -- " + self.msg
+	def addU8(self, x):
+		self.msg += chr(x)
+	def addU16(self, x):
+		self.msg += chr(x & 0x00FF) + chr((x & 0xFF00) >> 8) 
+	def addU32(self, x):
+		self.addU16(x & 0x0000FFFF)
+		self.addU16(x & 0xFFFF0000 >> 8)
+	def addString(self, x):
+		self.addU16(len(x))
+		self.msg += x
+	##
 	def decryptRSA(self):
 		decrypted = rsa.decrypt(self.msg[:128])
 		self.msg = decrypted
+	def decryptXTEA(self, key):
+		msg = ""
+		for i in xrange(len(self.msg) / 8):
+			msg += xtea.xtea_decrypt(key, self.msg[i*8:(i+1)*8], endian='<')
+		self.msg = msg
+	def checksumAdler(self):
+		checksum = zlib.adler32(self.msg)
+		self.msg += chr(checksum & 0xFF) + chr((checksum & 0xFF00) >> 8) + chr((checksum & 0xFF0000) >> 16) + chr((checksum & 0xFF000000) >> 24)
+	def encryptXTEA(self, key):
+		# prefix with message size
+		size = chr(len(self.msg) & 0x00FF) + chr((len(self.msg) & 0xFF00) >> 8)
+		self.msg = size + self.msg
 
+		# pad to 8
+		self.msg += '\0' * (8-(len(self.msg) % 8))
+		for i in self.msg:
+			print hex(ord(i)),
+
+		# encrypt
+		msg = ""
+		for i in xrange(len(self.msg) / 8):
+			msg += xtea.xtea_encrypt(key, self.msg[i*8:(i+1)*8], endian='<')
+		self.msg = msg
 #################################################
 
 class Connection(threading.Thread):
 
 		init_netmsg.decryptRSA()
 		
-		key = [	init_netmsg.readU32(), 
-			init_netmsg.readU32(), 
-			init_netmsg.readU32(), 
-			init_netmsg.readU32()]
-		print "Key: " + str(key)
+		self.key = init_netmsg.readCharacters(16) # 4 x uint32
+		#init_netmsg.decryptXTEA(self.key)
+		
+		account = init_netmsg.readString()
+		password = init_netmsg.readString()
+		hwconfig = init_netmsg.readCharacters(47)
+
+		##
+		output_msg = NetworkMessage()
+		output_msg.addU8(0x0A)
+		output_msg.addString("This is just an experiment with logging in.")	
+		output_msg.encryptXTEA(self.key)
+		output_msg.checksumAdler()
+		output_msg.sendMessage(self.mSocket)
+
 		self.mSocket.close()
 
 class GameworldConnection(Connection):

File xtea.py

View file
+## {{{ http://code.activestate.com/recipes/496737/ (r7)
+""" 
+XTEA Block Encryption Algorithm
+
+Author: Paul Chakravarti (paul_dot_chakravarti_at_gmail_dot_com)
+License: Public Domain
+
+This module provides a Python implementation of the XTEA block encryption
+algorithm (http://www.cix.co.uk/~klockstone/xtea.pdf). 
+
+The module implements the basic XTEA block encryption algortithm
+(`xtea_encrypt`/`xtea_decrypt`) and also provides a higher level `crypt`
+function which symmetrically encrypts/decrypts a variable length string using
+XTEA in OFB mode as a key generator. The `crypt` function does not use
+`xtea_decrypt` which is provided for completeness only (but can be used
+to support other stream modes - eg CBC/CFB).
+
+This module is intended to provide a simple 'privacy-grade' Python encryption
+algorithm with no external dependencies. The implementation is relatively slow
+and is best suited to small volumes of data. Note that the XTEA algorithm has
+not been subjected to extensive analysis (though is believed to be relatively
+secure - see http://en.wikipedia.org/wiki/XTEA). For applications requiring
+'real' security please use a known and well tested algorithm/implementation.
+
+The security of the algorithm is entirely based on quality (entropy) and
+secrecy of the key. You should generate the key from a known random source and
+exchange using a trusted mechanism. In addition, you should always use a random
+IV to seed the key generator (the IV is not sensitive and does not need to be
+exchanged securely)
+
+    >>> import os
+    >>> iv = 'ABCDEFGH'
+    >>> z = crypt('0123456789012345','Hello There',iv)
+    >>> z.encode('hex')
+    'fe196d0a40d6c222b9eff3'
+    >>> crypt('0123456789012345',z,iv)
+    'Hello There'
+
+""" 
+
+import struct
+
+def crypt(key,data,iv='\00\00\00\00\00\00\00\00',n=32):
+    """
+        Encrypt/decrypt variable length string using XTEA cypher as
+        key generator (OFB mode)
+        * key = 128 bit (16 char) 
+        * iv = 64 bit (8 char)
+        * data = string (any length)
+
+        >>> import os
+        >>> key = os.urandom(16)
+        >>> iv = os.urandom(8)
+        >>> data = os.urandom(10000)
+        >>> z = crypt(key,data,iv)
+        >>> crypt(key,z,iv) == data
+        True
+
+    """
+    def keygen(key,iv,n):
+        while True:
+            iv = xtea_encrypt(key,iv,n)
+            for k in iv:
+                yield ord(k)
+    xor = [ chr(x^y) for (x,y) in zip(map(ord,data),keygen(key,iv,n)) ]
+    return "".join(xor)
+
+def xtea_encrypt(key,block,n=32,endian="!"):
+    """
+        Encrypt 64 bit data block using XTEA block cypher
+        * key = 128 bit (16 char) 
+        * block = 64 bit (8 char)
+        * n = rounds (default 32)
+        * endian = byte order (see 'struct' doc - default big/network) 
+
+        >>> z = xtea_encrypt('0123456789012345','ABCDEFGH')
+        >>> z.encode('hex')
+        'b67c01662ff6964a'
+
+        Only need to change byte order if sending/receiving from 
+        alternative endian implementation 
+
+        >>> z = xtea_encrypt('0123456789012345','ABCDEFGH',endian="<")
+        >>> z.encode('hex')
+        'ea0c3d7c1c22557f'
+
+    """
+    v0,v1 = struct.unpack(endian+"2L",block)
+    k = struct.unpack(endian+"4L",key)
+    sum,delta,mask = 0L,0x61C88647L,0xffffffffL # delta was: 0x9e3779b9L
+    for round in range(n):
+        v0 = (v0 + (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask
+        sum = (sum + delta) & mask
+        v1 = (v1 + (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask
+    return struct.pack(endian+"2L",v0,v1)
+
+def xtea_decrypt(key,block,n=32,endian="!"):
+    """
+        Decrypt 64 bit data block using XTEA block cypher
+        * key = 128 bit (16 char) 
+        * block = 64 bit (8 char)
+        * n = rounds (default 32)
+        * endian = byte order (see 'struct' doc - default big/network) 
+
+        >>> z = 'b67c01662ff6964a'.decode('hex')
+        >>> xtea_decrypt('0123456789012345',z)
+        'ABCDEFGH'
+
+        Only need to change byte order if sending/receiving from 
+        alternative endian implementation 
+
+        >>> z = 'ea0c3d7c1c22557f'.decode('hex')
+        >>> xtea_decrypt('0123456789012345',z,endian="<")
+        'ABCDEFGH'
+
+    """
+    v0,v1 = struct.unpack(endian+"2L",block)
+    k = struct.unpack(endian+"4L",key)
+    delta,mask = 0x61C88647L,0xffffffffL # delta was: 0x9e3779b9L
+    sum = 0xC6EF3720L #(delta * n) & mask
+    for round in range(n):
+        v1 = (v1 - (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask
+        sum = (sum - delta) & mask
+        v0 = (v0 - (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask
+    return struct.pack(endian+"2L",v0,v1)
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
+## end of http://code.activestate.com/recipes/496737/ }}}