Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Need Python Code Converted To Delphi

Posted on 2010-11-28
1
Medium Priority
?
423 Views
Last Modified: 2016-09-29
The most important block is tlsobject, thank you.


def P_hash(secret, seed, length, hashfunc):
    a = {}
    a[0] = seed
    s = ""
    n = 1
    while len(s) < length:
        if n not in a:
            a[n] = hmac.new(secret, a[n-1], hashfunc).digest()
        s += hmac.new(secret, a[n] + seed, hashfunc).digest()
        n += 1
        
    return s[0:length]
        
def binaryxor(s1, s2):
    out = ""
    for i in xrange(len(s1)):
        out += chr(ord(s1[i]) ^ ord(s2[i]))
        
    return out
    
def PRF(secret, label, seed, size):
    slen = (len(secret) + 1) / 2
    a = P_hash(secret[:slen], label + seed, size, hashlib.md5)
    b = P_hash(secret[-slen:], label + seed, size, hashlib.sha1)
    return binaryxor(a, b)
    
def makerandomdata():
    st = ""
    for i in xrange(28):
        st += chr(random.randint(0, 255))
        
    return struct.pack(">L", int(time.time())) + st
    

class tlsobject(object):
    def __init__(self, logger, is_server = True):
        self.logger = logger
        self.is_server = is_server
        self.serverrandom = ""
        self.clientrandom = ""
        self.pre_master_secret = ""
        self.master_secret = ""
        
        self.allhandshakedata = ""
        self.version = "\x03\x01"
        self.client_encryption = False
        self.server_encryption = False
        
        self.clientseqnum = 0
        self.serverseqnum = 0
        
    def init_cryptosystem(self):
        self.master_secret = PRF(self.pre_master_secret, "master secret", self.clientrandom + self.serverrandom, 48)

        key_block = PRF(self.master_secret, "key expansion", self.serverrandom + self.clientrandom, 64)
        self.client_write_MAC = key_block[0:16]
        self.server_write_MAC = key_block[16:32]
        self.client_write_key = key_block[32:48]
        self.server_write_key = key_block[48:64]
        self.clientcrypt = ARC4.new(self.client_write_key)
        self.servercrypt = ARC4.new(self.server_write_key)

    def parsedata(self, data):
        appdata = []
        i = 0
        while i < len(data):
            header = data[i:i+5]
            if len(header) != 5:
                self.logger.error("Not enough data for header! %s %d", binascii.b2a_hex(data), i)
                sys.exit()
                
            i += 5
            contenttype = ord(header[0])
            version = header[1:3]
            if version != self.version:
                self.logger.error("Invalid version %d", repr(version))
                sys.exit()
                
            size = struct.unpack(">H", header[3:5])[0]
            fragment = data[i:i+size]
            if len(fragment) != size:
                self.logger.error("Not enough data for fragment! %s %d %d", binascii.b2a_hex(data), i, size)
                sys.exit()
            
            i += size
            
            self.logger.debug("Found content %d %d", contenttype, size)
            
            if (self.is_server and self.client_encryption) or (not self.is_server and self.server_encryption):
                fragment = self.decrypt_and_check_mac(contenttype, fragment)
                
            if contenttype == 20:
                self.parse_cipherchange(fragment)
            elif contenttype == 22:
                self.parse_handshake(fragment)
            elif contenttype == 23:
                self.logger.debug("Got application data %s", binascii.b2a_hex(fragment))
                appdata.append(fragment)
            else:
                self.logger.error("Unhandled content type %s %d", binascii.b2a_hex(fragment), contenttype)
                sys.exit()
                
        return appdata
        
    def decrypt_and_check_mac(self, contenttype, ciphertext):
        if self.is_server:
            plaintext = self.clientcrypt.decrypt(ciphertext)
            fragment = plaintext[:-16]
            MAC = plaintext[-16:]
            calcMAC = hmac.new(self.client_write_MAC, struct.pack(">Q", self.clientseqnum) + chr(contenttype) + self.version + struct.pack(">H", len(fragment)) + fragment, hashlib.md5).digest()
            if MAC != calcMAC:
                self.logger.error("DIFFERING MACS! %s %s", binascii.b2a_hex(plaintext), binascii.b2a_hex(fragment + calcMAC))
                sys.exit()
            
            self.clientseqnum += 1
            
            return fragment
            
        else:
            plaintext = self.servercrypt.decrypt(ciphertext)
            fragment = plaintext[:-16]
            MAC = plaintext[-16:]
            calcMAC = hmac.new(self.server_write_MAC, struct.pack(">Q", self.serverseqnum) + chr(contenttype) + self.version + struct.pack(">H", len(fragment)) + fragment, hashlib.md5).digest()
            if MAC != calcMAC:
                self.logger.error("DIFFERING MACS! %s %s", binascii.b2a_hex(plaintext), binascii.b2a_hex(fragment + calcMAC))
                sys.exit()
            
            self.serverseqnum += 1
            
            return fragment
            
    def parse_cipherchange(self, fragment):
        if fragment != "\x01":
            self.logger.error("Weird cipher change fragment! %s", repr(fragment))
            sys.exit()
        
        if self.is_server:
            self.client_encryption = True
        else:
            self.server_encryption = True
            
    def parse_handshake(self, fragment):
        i = 0
        while i < len(fragment):
            header = fragment[i:i+4]
            if len(header) != 4:
                self.logger.error("Not enough data for header! %s %d", binascii.b2a_hex(fragment), i)
                sys.exit()
            i += 4
            handshaketype = ord(header[0])
            size = struct.unpack(">L", header)[0] & 0x00ffffff
            handshakedata = fragment[i:i+size]
            if len(handshakedata) != size:
                self.logger.error("not enough data for handshake data! %s %d %d", binascii.b2a_hex(fragment), i, size)
                sys.exit()
            i += size
            
            self.logger.debug("Found handshake %d %d", handshaketype, size)
            
            if handshaketype == 1:
                self.parse_clienthello(handshakedata)
            elif handshaketype == 2:
                self.parse_serverhello(handshakedata)
            elif handshaketype == 11:
                self.parse_certificate(handshakedata)
            elif handshaketype == 14:
                if size != 0:
                    self.logger.error("Server_hello_done has nonstandard length %d", size)
                    sys.exit()
            elif handshaketype == 16:
                self.parse_clientkeyexchange(handshakedata)
            elif handshaketype == 20:
                self.parse_finished(handshakedata)
            else:
                self.logger.error("Unhandled handshake %d", handshaketype)
                sys.exit()
                
        self.allhandshakedata += fragment
        
    def parse_clienthello(self, data):
        version = data[0:2]
        if version != self.version:
            self.logger.error("Invalid version %s", repr(version))
            sys.exit()
        self.clientrandom = data[2:34]
        extrasettings = data[34:]
        if extrasettings != binascii.a2b_hex("00001600040005000a000900640062000300060013001200630100"):
            self.logger.warning("Unexpected client settings %s %s", binascii.b2a_hex(data), binascii.b2a_hex(extrasettings))
        
    def parse_serverhello(self, data):
        version = data[0:2]
        if version != self.version:
            self.logger.error("Invalid version %s", repr(version))
            sys.exit()
        self.serverrandom = data[2:34]
        sessionidlength = ord(data[34])
        if sessionidlength != 32:
            self.logger.error("Nonstandard session ID length! %d", sessionidlength)
            sys.exit()
            
        self.sessionid = data[35:67]
        if data[67:70] != "\x00\x04\x00":
            self.logger.error("Nonstandard cipher suite! %s", repr(data[67:70]))
            sys.exit()
        
    def parse_certificate(self, data):
        certhash = hashlib.md5(data).hexdigest()
        
        # 512-bit RSA key
        if certhash == "81e1e85248f3de66f88f56c0fdf6614c":
            self.rsakey = real_key_2_sign
            self.rsasize = 512
        elif certhash == "0fbfa0185aa1f7972fa4d63b0594ca6a":
            self.rsakey = fake_key2_sign
            self.rsasize = 512
        elif certhash == "0a1ba2bb7dcf9aec94e9c7df115d60f5":
            self.rsakey = real_key_sign
            self.rsasize = 2048
        else:
            self.logger.error("Unknown certificate %s %s", certhash, binascii.b2a_hex(data))
            sys.exit()
        
    def parse_clientkeyexchange(self, data):
        length = struct.unpack(">H", data[0:2])[0]
        if len(data) != length + 2:
            self.logger.error("Client key exchange length failed!")
            sys.exit()
            
        decryptedkey = self.rsakey.decrypt(data[2:])
        self.logger.debug("Decrypted key %s" , binascii.b2a_hex(decryptedkey))
        self.pre_master_secret = decryptedkey[-48:]
        self.init_cryptosystem()


    def parse_finished(self, handshakedata):
        if self.is_server:
            finishedmessage = PRF(self.master_secret, "client finished", hashlib.md5(self.allhandshakedata).digest() + hashlib.sha1(self.allhandshakedata).digest(), 12)
            
            if handshakedata != finishedmessage:
                self.logger.error("Finished handshake doesn't match! %s %s", binascii.b2a_hex(finishedmessage), binascii.b2a_hex(handshakedata))
                sys.exit()
        else:
            finishedmessage = PRF(self.master_secret, "server finished", hashlib.md5(self.allhandshakedata).digest() + hashlib.sha1(self.allhandshakedata).digest(), 12)
            
            if handshakedata != finishedmessage:
                self.logger.error("Finished handshake doesn't match! %s %s", binascii.b2a_hex(finishedmessage), binascii.b2a_hex(handshakedata))
                sys.exit()

    def make_message(self, contenttype, data):
        if contenttype == 22:
            self.allhandshakedata += data
            
        if (self.is_server and self.server_encryption) or (not self.is_server and self.client_encryption):
            if self.is_server:
                MAC = hmac.new(self.server_write_MAC, struct.pack(">Q", self.serverseqnum) + chr(contenttype) + self.version + struct.pack(">H", len(data)) + data, hashlib.md5).digest()
                data = self.servercrypt.encrypt(data + MAC)
                self.serverseqnum += 1
            else:
                MAC = hmac.new(self.client_write_MAC, struct.pack(">Q", self.clientseqnum) + chr(contenttype) + self.version + struct.pack(">H", len(data)) + data, hashlib.md5).digest()
                data = self.clientcrypt.encrypt(data + MAC)
                self.clientseqnum += 1
            
        message = chr(contenttype) + self.version + struct.pack(">H", len(data)) + data
        return message
        
    def make_handshake(self, handshaketype, data):
        handshake = chr(handshaketype) + struct.pack(">L", len(data))[1:4] + data
        return handshake

    def make_clienthello(self):
        self.clientrandom = makerandomdata()
        
        sessionid = ""
        ciphercompressuite = binascii.a2b_hex("001600040005000a000900640062000300060013001200630100")
        
        handshake = self.make_handshake(1, self.version + self.clientrandom + chr(len(sessionid)) + sessionid + ciphercompressuite)
        
        return self.make_message(22, handshake)
        
    def make_serverhello(self, sessionid, certificate):
        self.serverrandom = makerandomdata()
        self.sessionid = sessionid
        
        # FIX LATER
        if len(certificate) == 469:
            self.rsakey = fake_key2
        elif len(certificate) == 1189:
            self.rsakey = fake_key
        
        ciphercompressuite = "\x00\x04\x00"
        handshake = self.make_handshake(2, self.version + self.serverrandom + chr(len(sessionid)) + sessionid + ciphercompressuite)
        
        certificates = struct.pack(">L", len(certificate))[1:4] + certificate
        handshake += self.make_handshake(11, struct.pack(">L", len(certificates))[1:4] + certificates)
        
        handshake += self.make_handshake(14, "")
        
        return self.make_message(22, handshake)

    def make_serverchangefinish(self):
        # chance cipher spec
        message = self.make_message(20, "\x01")
        
        self.server_encryption = True
        
        finishedmessage = PRF(self.master_secret, "server finished", hashlib.md5(self.allhandshakedata).digest() + hashlib.sha1(self.allhandshakedata).digest(), 12)
        message += self.make_message(22, self.make_handshake(20, finishedmessage))
        
        return message
        
    def make_client_key_exchange(self):
        st = ""
        for i in xrange(46):
            st += chr(random.randint(0, 255))
        
        self.pre_master_secret = self.version + st
        
        if self.rsasize == 512:
            encrypted = self.rsakey.encrypt("\x02" + "\xff" * 13 + "\x00" + self.pre_master_secret, 0)[0]
            encrypted = encrypted.rjust(64, "\x00")
            if len(encrypted) != 64:
                self.logger.error("Invalid size after encrypt %d", len(encrypted))
                sys.exit()
                
            handshake = self.make_handshake(16, struct.pack(">H", len(encrypted)) + encrypted)
            
            message = self.make_message(22, handshake)
        elif self.rsasize == 2048:
            encrypted = self.rsakey.encrypt("\x02" + "\xff" * 205 + "\x00" + self.pre_master_secret, 0)[0]
            encrypted = encrypted.rjust(256, "\x00")
            if len(encrypted) != 256:
                self.logger.error("Invalid size after encrypt %d", len(encrypted))
                sys.exit()
                
            handshake = self.make_handshake(16, struct.pack(">H", len(encrypted)) + encrypted)
            
            message = self.make_message(22, handshake)
        else:
            self.logger.error("Unknown RSA size %d", self.rsasize)
            sys.exit()
            
        message += self.make_message(20, "\x01")
        
        self.init_cryptosystem()
        self.client_encryption = True
        
        finishedmessage = PRF(self.master_secret, "client finished", hashlib.md5(self.allhandshakedata).digest() + hashlib.sha1(self.allhandshakedata).digest(), 12)
        message += self.make_message(22, self.make_handshake(20, finishedmessage))
        
        return message
        
    def make_appdata(self, data):
        return self.make_message(23, data)

Open in new window

0
Comment
Question by:rotem156
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
 
LVL 14

Accepted Solution

by:
systan earned 1000 total points
ID: 34225304
That code's encrypt and decrypt data, function that ask for key/seed to encrypt or decrypt using certificates, the code also ask as client/server and depends on the user option.

Why need to convert, while you can look for that functions here.
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_20554541.html
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction On September 29, 2012, the Python 3.3.0 was released; nothing extremely unexpected,  yet another, better version of Python. But, if you work in Microsoft Windows, you should notice that the Python Launcher for Windows was introduced wi…
Learn the basics of lists in Python. Lists, as their name suggests, are a means for ordering and storing values. : Lists are declared using brackets; for example: t = [1, 2, 3]: Lists may contain a mix of data types; for example: t = ['string', 1, T…
Learn the basics of while and for loops in Python.  while loops are used for testing while, or until, a condition is met: The structure of a while loop is as follows:     while <condition>:         do something         repeate: The break statement m…
Suggested Courses

618 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question