David B
David B

Reputation: 1

generate master key tls1.2

I'm trying to figure out/generate the master key manually for an https conversation using command line in openssl. I have kept track in my HTTPS conversation all of the pertinent data to the point of the client key exchange, change cipher spec, encrypted handshake message. What I have read in the RFC5246 so far is that to do this requires: master_secret = PRF(pre_master_secret, "master secret",ClientHello.random + ServerHello.random) [0..47];

Which reading further in the RFC that would be equal to:

P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + HMAC_hash(secret, A(2) + seed) + ... Where secret = premaster secret from client Where A(0)=SEED = “master secret”+clienthello.random+serverhello.random

A(1)=HMAC_hash(secret,A(0)) A(2)= HMAC_hash(secret,A(1))

and iterate through until I get the needed 48 bytes of the master secret/key

If I am correct in my assumptions I was hoping to iterate through use command line of openssl to get my 48 bytes if that is possible something like this 2 times or as many needed to get 48 bytes. I understand this would just echo to the screen the value which I would of course store to be used in the next iteration. echo -n "value" | openssl dgst -sha1 -hmac "key"

Am I off base on my interpretation of the RFC or is something like this possible? Am I missing any steps if my interpretation is correct? Regards David B

Upvotes: 0

Views: 455

Answers (1)

Zeta
Zeta

Reputation: 981

Your question is not clear to me.(English is not my mother tongue.) But I implemented prf function myself. And tested with test vector. It works fine.

template<class H> class PRF
{//H is hash function usually sha256
public:
    template<class It> void secret(const It begin, const It end) {
        for(It it = begin; it != end; it++) secret_.push_back(*it);
        hmac_.key(secret_.begin(), secret_.end());
    }
    void label(const char* p) {
        while(*p) label_.push_back(*p++);
    }
    template<class It> void seed(const It begin, const It end) {
        for(It it = begin; it != end; it++) seed_.push_back(*it);
    }
    std::vector<unsigned char> get_n_byte(int n) {
        auto seed = label_;//seed = label + seed_
        seed.insert(seed.end(), seed_.begin(), seed_.end());
        std::vector<unsigned char> r, v;
        std::vector<std::array<unsigned char, H::output_size>> vA;
        vA.push_back(hmac_.hash(seed.begin(), seed.end()));//A(1)
        while(r.size() < n) {
            v.clear();
            v.insert(v.end(), vA.back().begin(), vA.back().end());
            v.insert(v.end(), seed.begin(), seed.end());
            auto h = hmac_.hash(v.begin(), v.end());
            r.insert(r.end(), h.begin(), h.end());
            vA.push_back(hmac_.hash(vA.back().begin(), vA.back().end()));//A(i+1)
        }
        while(r.size() != n) r.pop_back();
        return r;
    }

protected:
    HMAC<H> hmac_;
    std::vector<unsigned char> secret_, label_, seed_;
};

As you can see in the code, A(i+1) is generated by hashing formerly generated one. Code is not abstract, but a concrete example.

I hope you can get the info that you need in this code.

Upvotes: 0

Related Questions