I got an answer to my original question
here
hopefully it is ok to ask a follow up question by posting another question. From my original question above I was able to decrypt the client pre master secret/key using my private key as it was explained to me using
openssl rsautl -in cpre.key -inkey key.pem -decrypt -out spre.key
This seems pretty straight forward and it created a 48 byte file. I do realize what I am doing is not going to actually decrypt or encrypt the https traffic I am working on this in small steps. The next step from my reading is going to be to generate the master secret/key and from the answer on my previous post it seems I should be able to also do this with openssl which I am struggling a bit here to do this. I've come up with a variation of openssl dgst
echo -n 'value' | openssl dgst -sha256 -mac hmac -macopt hexkey:$(hexkey)
where value is "master secret"+client.random+server.random and hexkey is my decrypted pre master secret from the previous step. Am I doing this step correctly? From the way I understand the RFC since this first time through it produces 32 bytes and the RFC explains it will be 48 bytes. The way I am interpreting the RFC is that I need to take that result and pass it through again which generates an additional 32 bytes of which I take the first 16 and concatenate that on the end of the first 32 to get my 48 bytes for the master secret/key. Am I completely off on this next step after I have decrypted and have the server side pre master key?
Thanks
David B
Best Answer
Preliminarily, I hope you didn't actually do what you showed. Except for the labels, all the data used in TLS key derivation is binary data that cannot accurately be given as argument to a shell
echo
command or any other command, except possibly the builtin version inzsh
if you disable escapes, and certainly cannot be 'typed' (even cut&pasted) in a literal argument with singlequotes.If you actually have the data in files, those can be used. Binary data can be read from, and written to, files -- at least on the platforms OpenSSL supports. If you don't have files (but do have pipes) you can work-around this by passing the data in hex, and except for
-macopt hexkey:
which already takes hex, using either a program likexxd -r
, orprintf
with the hex formed into escapes, orecho
with the hex formed into non-portable escapes, or hacks like GNUsed s///e
, or a more general programawk
orperl
, to convert the hex to binary for input toopenssl
. And when necessary similar hacks to convert binary output to hex, butdgst -mac hmac
can output in hex as long as you remove theblahblah=(sp)
from the front.More substantively, running the first HMAC output back through itself only gives you the 'A' blocks, which you then run through another layer of HMACs to get the actual output 'P_hash'. See https://crypto.stackexchange.com/questions/46549/tls-1-2-prf-with-hmac-sha256 which is effectively the same question using a test vector published at https://www.ietf.org/mail-archive/web/tls/current/msg03416.html except I answered in Java. Here is the OpenSSL commandline equivalent:
If you can get your code to replicate this, it should work for the actual TLS1.2 handshake also, adjusted for the correct lengths: 48 for the master secret, and depending on the ciphersuite for the working keys.