0

I have been trying to calculate the master secret used to encrypt some data using the client public key B, the server private key a and the client and server random values. I have calculated k=B^a, which to my understanding gives me the premaster secret. I then input this together with the random values into the following PRF function (page 15 of this pdf):

def prf(secret,label,seed,numblocks):
    seed=label+seed
    output = ''
    a=hmac.new(secret,msg=seed,digestmod=hashlib.sha256).digest()
    for j in range(numblocks):
        output += hmac.new(secret,msg=a+seed,digestmod=hashlib.sha256).digest()
        a=hmac.new(secret,msg=a,digestmod=hashlib.sha256).digest()
    return output
def master_secret(pms,client_random,server_random):
    out=prf(pms,"master secret",client_random+server_random,2)
    return out[:48]

According to the RFC specification for TLS1.2, this should output the master secret, but when verifying it with the data I have, it is wrong. Where is my mistake?

1 Answer 1

1

After trying to solve the problem for several hours, I noticed that there was a mistake in the server/client random values which caused the function to return a wrong value; the code posted above is correct.

EDIT: here is a working example to verify the code works:

#!/usr/bin/python2
import hmac
import hashlib
pre_secret = '\x77\xdc\x17\xff\x36\xd7\xaf\x80\x99\x9c\xdd\x47\xbf\x5d\x45\x78\xd2\x82\xb6\x71\x54\x74\x26\x88\xac\xff\x70\x48\x94\x34\xef\x58\x68\x08\x63\xb5\xad\x31\x4e\x8a\xf7\xf1\xfa\xa7\x15\x05\xf1\x4c\x5d\xa5\x40\x17\x98\x48\xb7\x9e\x4b\x19\x5f\x40\xc2\x9c\x6e\x29\x0a\x68\xeb\x22\xa3\xee\xb8\x5b\xe5\xce\x8f\x91\x73\x58\x33\xba\x15\xa0\x0c\x87\xbd\x3f\x0a\x9a\x03\xc0\xf6\x3c\xe3\x60\x79\xa8\xb4\x6f\x25\x26\xa7\xe1\x7f\x37\x51\x76\x59\x0b\xb0\x4f\x63\x35\xd2\x6d\x50\x8f\x55\xde\x19\x61\x55\x93\x56\x72\xde\x98\x42\x78\x51\xe2\x1a\x7e\xe1\xb7\x6a\x68\xfa\x55\x02\x64\x33\x04\x79\x33\x06\xf4\x10\x46\x4b\x40\xaf\xce\x33\x3d\x46\x01\xdb\xc9\x41\x54\x08\x1f\xfa\x3d\x9e\x88\x34\x8d\x64\x2f\x85\xa6\x46\x4d\xe7\xb1\x72\x42\x4f\xf9\xf4\xc7\x7e\x46\x2e\xed\xb1\xeb\x2d\x28\x95\x12\xf8\xc3\xf2\x2e\xbe\xde\xa2\xdd\xf6\x3a\x62\x0f\x9d\x17\x71\xf8\xf2\x07\x52\x72\x17\xba\x03\xbf\x1a\x2a\x26\xc6\x39\x87\xfb\xc8\x09\x48\x32\xf5\x2a\x89\x3d\x90\x1a\x74\x81\x4b\x2e\x24\xea\xb0\x75\x00\xce\x3f\x26\xe7\x1f\xa2\x80\xe7\x70\xf5\x74\xb0\x91\xa5\xd7\x1a\xbc\x40\x70\x05\x23\x5b\x19\x9b\xe7\x57\x29\xb9\x18\x32\xa9\xc2\xc2\xdc\xc5\x5b\xca\xfb\xb6\x25\x93\x76\x74\x09\x3c\x57\xde\x75\x07\x6e\x11\xe9\x2b\x9d\xd1\x1b\xa7\xe7\x1f\x21\x9e\xc6\x49\x80\xa4\x84\x8d\xd0\xc9\x75\x3f\x5c\xd9\x8b\x88\x6f\x5a\x49\x0e\xd6\x60\x87\x5c\x36\xf9\xe1\x99\x19\x26\xa4\xbd\x9a\x5a\xd5\x30\x9c\xa1\xe7\x99\x3a\x3d\xfd\x08\xeb\xf0\x51\x89\x2d\xd8\x0f\x70\x90\xde\x5f\x8e\xb2\x52\x05\x9b\x4d\x12\x6a\xff\x14\x17\x7f\xa5\x28\xf4\x3b\x55\xcf\x49\x09\x56\x1d\x61\xcd\x27\x5e\x02\x05\x87\x18\xf3\x75\xfa\x43\x40\x21\x6c\xe1\xc4\x51\x5b\xfe\xb6\x34\xea\x8f\x0d\x92\x0a\xe2\x79\xb7\xd5\x46\x3b\xf2\x3f\x6b\x76\xea\x48\xb8\xa7\xf1\xf6\x51\x84\x08\x43\x18\x4b\x63\x8f\x82\x56\x52\x13\xd8\x73\xc7\xd1\x17\xfa\xaa\x98\x21\x8f\x78\x13\x61\x5f\x43\xba\x32\x48\xbc\xc9\x60\xc8\xfa\x60\x57\x1b\xc9\x15\xee\x2d\xb8\xce\xb3\xea\xdd\x44\x19\x4d\x69\x63\xee\xc8\x7f\xd4\xf8\x80\x7d\x08\x82\xa8\xbe\x84\x4d\x92\x06\xa7\x92\x4e\x8d\xf1\xa1\x75\x07\xd5\x04\xb2\x7e\x93\xb9\x24\x11\x64\x6b\x23\xe4\x2e\x83\x4f\x60'
server_random = '\x89\x68\xc0\x01\xfc\xf6\xc1\xbf\x0d\xff\xe9\x3e\x5a\x98\x81\x04\x6c\x37\xce\x9f\x36\xb3\x76\x61\xcb\x0d\x26\x84\x50\x4b\x0e\xaf'
client_random = '\x59\x6c\xaa\x43\x97\xad\xb3\xe5\x08\xd6\x92\xa6\x2b\xe2\xc8\xc6\x98\x42\x0b\x24\x74\x1d\xd8\x9d\x32\xfd\x01\xb9\x70\xbe\x13\xde'
expected_output = '47acd374aad14df1e3c1636c234c186a63ebfb35a1c1b864fdf3204597f7b7ce29f6a41931ac41e8f3f0addb1d322c42'
def prf(secret,label,seed,numblocks):
        seed=label+seed
        output = ''
        a=hmac.new(secret,msg=seed,digestmod=hashlib.sha256).digest()
        for j in range(numblocks):
                output += hmac.new(secret,msg=a+seed,digestmod=hashlib.sha256).digest()
                a=hmac.new(secret,msg=a,digestmod=hashlib.sha256).digest()
        return output
def master_secret(pms,client_random,server_random):
        out=prf(pms,"master secret",client_random+server_random,2)
        return out[:48]
print(''.join([hex(ord(b))[2:].zfill(2) for b in master_secret(pre_secret, client_random, server_random)]) == expected_output)
5
  • Interesting stuff that. Might try that python bit myself some time. If it now works to your satisfaction you could accept your own reply as "Answer". -- Maybe add a "run this on your python prompt and see that it works" session transcript as well? (I'd be interested.) Commented Nov 23, 2017 at 15:25
  • @StackzOfZtuff I added my complete code so if you need it, here you go
    – Lukor
    Commented Nov 23, 2017 at 15:32
  • Great! Thanks. Can't get it to run though. (SyntaxError: EOL while scanning string literal) Something is broken with the line breaks in the string literal. I couldn't find a way to fix it. (Then I only got: ValueError: invalid \x escape.) Could you try again with no manually inserted hard line breaks? Commented Nov 23, 2017 at 17:50
  • @StackzOfZtuff actually there should be no line breaks, I'll fix that as soon as I get home
    – Lukor
    Commented Nov 23, 2017 at 17:58
  • @StackzOfZtuff I fixed the line breaks, it should work now (it does on my PC)
    – Lukor
    Commented Nov 24, 2017 at 1:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .