commit 984add2da2e62b8c102f60a671717b240a004bac Author: Damian Johnson atagar@torproject.org Date: Wed Jan 31 11:57:51 2018 -0800
Change KDF to a named tuple
Been going back and forth on this but yeah, think it's a bit nicer this way. --- stem/client/__init__.py | 46 +++++++++++++++------------------ test/settings.cfg | 2 +- test/unit/client/__init__.py | 2 +- test/unit/client/{kdf_tor.py => kdf.py} | 17 ++++-------- 4 files changed, 28 insertions(+), 39 deletions(-)
diff --git a/stem/client/__init__.py b/stem/client/__init__.py index 4c6bdb12..f3e842c6 100644 --- a/stem/client/__init__.py +++ b/stem/client/__init__.py @@ -12,7 +12,9 @@ a wrapper for :class:`~stem.socket.RelaySocket`, much the same way as ::
split - splits bytes into substrings - KDF - KDF-TOR key derivative for TAP, CREATE_FAST handshakes, and hidden serivces + + KDF - KDF-TOR derivatived attributes + +- from_value - parses key material
Field - Packable and unpackable datatype. |- Size - Field of a static size. @@ -107,6 +109,7 @@ a wrapper for :class:`~stem.socket.RelaySocket`, much the same way as ===================== =========== """
+import collections import hashlib import io import struct @@ -461,45 +464,38 @@ class Certificate(Field): return _hash_attr(self, 'type_int', 'value')
-class KDF(object): +class KDF(collections.namedtuple('KDF', ['key_hash', 'forward_digest', 'backward_digest', 'forward_key', 'backward_key'])): """ - Tor's derived key for TAP, CREATE_FAST handshakes, and hidden service - protocols as defined tor-spec section 5.2.1. + Computed KDF-TOR derived values for TAP, CREATE_FAST handshakes, and hidden + service protocols as defined tor-spec section 5.2.1.
- :var bytes key_hash: expected derived key that proves knowledge of our shared - computed key + :var bytes key_hash: hash that proves knowledge of our shared key :var bytes forward_digest: forward digest hash seed :var bytes backward_digest: backward digest hash seed :var bytes forward_key: forward encryption key :var bytes backward_key: backward encryption key """
- def __init__(self, key_material): - value = KDF._value(key_material) - - self.key_hash, value = split(value, HASH_LEN) - self.forward_digest, value = split(value, HASH_LEN) - self.backward_digest, value = split(value, HASH_LEN) - self.forward_key, value = split(value, KEY_LEN) - self.backward_key, value = split(value, KEY_LEN) - @staticmethod - def _value(key): - """ - Computes the KDF-TOR value... - - K = H(K0 | [00]) | H(K0 | [01]) | H(K0 | [02]) | ... - """ + def from_value(key_material): + # Derived key material, as per... + # + # K = H(K0 | [00]) | H(K0 | [01]) | H(K0 | [02]) | ...
derived_key = '' - derived_key_len = KEY_LEN * 2 + HASH_LEN * 3 counter = 0
- while len(derived_key) < derived_key_len: - derived_key += hashlib.sha1(key + Size.CHAR.pack(counter)).digest() + while len(derived_key) < KEY_LEN * 2 + HASH_LEN * 3: + derived_key += hashlib.sha1(key_material + Size.CHAR.pack(counter)).digest() counter += 1
- return derived_key[:derived_key_len] + key_hash, derived_key = split(derived_key, HASH_LEN) + forward_digest, derived_key = split(derived_key, HASH_LEN) + backward_digest, derived_key = split(derived_key, HASH_LEN) + forward_key, derived_key = split(derived_key, KEY_LEN) + backward_key, derived_key = split(derived_key, KEY_LEN) + + return KDF(key_hash, forward_digest, backward_digest, forward_key, backward_key)
setattr(Size, 'CHAR', Size('CHAR', 1, '!B')) diff --git a/test/settings.cfg b/test/settings.cfg index 7af57181..4080ca2a 100644 --- a/test/settings.cfg +++ b/test/settings.cfg @@ -233,7 +233,7 @@ test.unit_tests |test.unit.client.size.TestSize |test.unit.client.address.TestAddress |test.unit.client.certificate.TestCertificate -|test.unit.client.kdf_tor.TestKdfTor +|test.unit.client.kdf.TestKDF |test.unit.client.cell.TestCell |test.unit.connection.authentication.TestAuthenticate |test.unit.connection.connect.TestConnect diff --git a/test/unit/client/__init__.py b/test/unit/client/__init__.py index ba93b3e6..91d3b2be 100644 --- a/test/unit/client/__init__.py +++ b/test/unit/client/__init__.py @@ -6,7 +6,7 @@ __all__ = [ 'address', 'cell', 'certificate', - 'kdf_tor', + 'kdf', 'size', ]
diff --git a/test/unit/client/kdf_tor.py b/test/unit/client/kdf.py similarity index 59% rename from test/unit/client/kdf_tor.py rename to test/unit/client/kdf.py index f356d2cd..56665d31 100644 --- a/test/unit/client/kdf_tor.py +++ b/test/unit/client/kdf.py @@ -1,5 +1,5 @@ """ -Unit tests for stem.client.kdf_tor. +Unit tests for stem.client.KDF. """
import unittest @@ -9,24 +9,17 @@ import stem.client KEY_1 = '\xec\xec.\xeb7R\xf2\n\xcb\xce\x97\xf4\x86\x82\x19#\x10\x0f\x08\xf0\xa2Z\xdeJ\x8f2\x8cc\xf6\xfa\x0e\t\x83f\xc5\xe2\xb3\x94\xa8\x13' KEY_2 = '\xe0v\xe4\xfaTB\x91\x1c\x81Gz\xa0\tI\xcb{\xc56\xcfV\xc2\xa0\x19\x9c\x98\x9a\x06\x0e\xc5\xfa\xb0z\x83\xa6\x10\xf6r"<b'
-DERIVED_1 = '\xca+\x81\x05\x14\x9d)o\xa6\x82\xe9B\xa8?\xf2\xaf\x85\x1b]6\xac\xcc\xbc\x91\xb1\xaf\xd7\xe0\xe9\x9dF#\xd8\xdbz\xe8\xe6\xca\x83,*\xe5scX\xbb+\xca \xcb\xa4\xbc\xad\x0f\x95\x0cO\xcc\xac\xf1\xc3\xbe\xc9\xe1\xf4\x90f\xdai\xf3\xf3\xf5\x14\xb5\xb9\x03U\xaf\x1e\x1b\xb1q||\x86A<_\xf7\xa0%\x86' -DERIVED_2 = '\xbc0\xf99\x8e;Te\xbb+\xdb\xabR3l\xb9f?\x07KZC8\xe7\xa15\xd1IS\xd9\xd4\x1e\x96\xf6\xcd\x82\x91\x0b}r\x7f\xc5\xc0\xb1/[\x97dW\xba\x82g\xe7m^\x06[\xe6\xf8\xb4\x83f>c\x8b\x0f\x03\xcc\x98\x1f~t\x88\xe1\x83\xec\xbf*_\x8cF\x0e1\xa9\x17\xce\xa6\xa3\xd1+]\x1f'
- -class TestKdfTor(unittest.TestCase): - def test_kdf_value(self): - self.assertEqual(DERIVED_1, stem.client.KDF._value(KEY_1)) - self.assertEqual(DERIVED_2, stem.client.KDF._value(KEY_2)) - - def test_kdf_attributes(self): - k1 = stem.client.KDF(KEY_1) +class TestKDF(unittest.TestCase): + def test_parsing(self): + k1 = stem.client.KDF.from_value(KEY_1) self.assertEqual('\xca+\x81\x05\x14\x9d)o\xa6\x82\xe9B\xa8?\xf2\xaf\x85\x1b]6', k1.key_hash) self.assertEqual('\xac\xcc\xbc\x91\xb1\xaf\xd7\xe0\xe9\x9dF#\xd8\xdbz\xe8\xe6\xca\x83,', k1.forward_digest) self.assertEqual('*\xe5scX\xbb+\xca \xcb\xa4\xbc\xad\x0f\x95\x0cO\xcc\xac\xf1', k1.backward_digest) self.assertEqual('\xc3\xbe\xc9\xe1\xf4\x90f\xdai\xf3\xf3\xf5\x14\xb5\xb9\x03', k1.forward_key) self.assertEqual('U\xaf\x1e\x1b\xb1q||\x86A<_\xf7\xa0%\x86', k1.backward_key)
- k2 = stem.client.KDF(KEY_1) + k2 = stem.client.KDF.from_value(KEY_1) self.assertEqual('\xca+\x81\x05\x14\x9d)o\xa6\x82\xe9B\xa8?\xf2\xaf\x85\x1b]6', k2.key_hash) self.assertEqual('\xac\xcc\xbc\x91\xb1\xaf\xd7\xe0\xe9\x9dF#\xd8\xdbz\xe8\xe6\xca\x83,', k2.forward_digest) self.assertEqual('*\xe5scX\xbb+\xca \xcb\xa4\xbc\xad\x0f\x95\x0cO\xcc\xac\xf1', k2.backward_digest)