/
hkdf.py
64 lines (51 loc) · 2.08 KB
/
hkdf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# SPDX-License-Identifier: GPL-2.0-only
# This file is part of Scapy
# See https://scapy.net/ for more information
# Copyright (C) 2017 Maxence Tury
"""
Stateless HKDF for TLS 1.3.
"""
import struct
from scapy.config import conf
from scapy.layers.tls.crypto.pkcs1 import _get_hash
if conf.crypto_valid:
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand
from cryptography.hazmat.primitives.hashes import Hash
from cryptography.hazmat.primitives.hmac import HMAC
class TLS13_HKDF(object):
def __init__(self, hash_name="sha256"):
self.hash = _get_hash(hash_name)
def extract(self, salt, ikm):
h = self.hash
hkdf = HKDF(h, h.digest_size, salt, None, default_backend())
if ikm is None:
ikm = b"\x00" * h.digest_size
return hkdf._extract(ikm)
def expand(self, prk, info, L):
h = self.hash
hkdf = HKDFExpand(h, L, info, default_backend())
return hkdf.derive(prk)
def expand_label(self, secret, label, hash_value, length):
hkdf_label = struct.pack("!H", length)
hkdf_label += struct.pack("B", 6 + len(label))
hkdf_label += b"tls13 "
hkdf_label += label
hkdf_label += struct.pack("B", len(hash_value))
hkdf_label += hash_value
return self.expand(secret, hkdf_label, length)
def derive_secret(self, secret, label, messages):
h = Hash(self.hash, backend=default_backend())
h.update(messages)
hash_messages = h.finalize()
hash_len = self.hash.digest_size
return self.expand_label(secret, label, hash_messages, hash_len)
def compute_verify_data(self, basekey, handshake_context):
hash_len = self.hash.digest_size
finished_key = self.expand_label(basekey, b"finished", b"", hash_len)
h = Hash(self.hash, backend=default_backend())
h.update(handshake_context)
hash_value = h.finalize()
hm = HMAC(finished_key, self.hash, default_backend())
hm.update(hash_value)
return hm.finalize()