Reputation: 1
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
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