commit d529c3e2a089fc397959b0bee7c012c31f878aa1 Author: Damian Johnson atagar@torproject.org Date: Sun May 26 11:44:53 2019 -0700
Move private hmac helpers into stem.connection
In taking a peek at one of our new stylistic warnings [1] I realized that stem.connection is using private methods of stem.util.connection that aren't used anywhere else. Clearly they belong with their sole user.
[1] /home/atagar/Desktop/stem/stem/util/connection.py line 766 - W504 line break after binary operator | _hmac_sha256(CRYPTOVARIABLE_EQUALITY_COMPARISON_NONCE, x) == --- stem/connection.py | 26 +++++++++++++++++++++++--- stem/util/connection.py | 32 -------------------------------- 2 files changed, 23 insertions(+), 35 deletions(-)
diff --git a/stem/connection.py b/stem/connection.py index 8a64c887..90997fb9 100644 --- a/stem/connection.py +++ b/stem/connection.py @@ -129,6 +129,8 @@ fine-grained control over the authentication process. For instance...
import binascii import getpass +import hashlib +import hmac import os
import stem.control @@ -147,6 +149,8 @@ AuthMethod = stem.util.enum.Enum('NONE', 'PASSWORD', 'COOKIE', 'SAFECOOKIE', 'UN CLIENT_HASH_CONSTANT = b'Tor safe cookie authentication controller-to-server hash' SERVER_HASH_CONSTANT = b'Tor safe cookie authentication server-to-controller hash'
+CRYPTOVARIABLE_EQUALITY_COMPARISON_NONCE = os.urandom(32) + MISSING_PASSWORD_BUG_MSG = """ BUG: You provided a password but despite this stem reported that it was missing. This shouldn't happen - please let us know about it! @@ -941,15 +945,18 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True) else: raise AuthChallengeFailed('Unable to parse AUTHCHALLENGE response: %s' % exc, cookie_path)
- expected_server_hash = stem.util.connection._hmac_sha256( + expected_server_hash = _hmac_sha256( SERVER_HASH_CONSTANT, cookie_data + client_nonce + authchallenge_response.server_nonce)
- if not stem.util.connection._cryptovariables_equal(authchallenge_response.server_hash, expected_server_hash): + authchallenge_hmac = _hmac_sha256(CRYPTOVARIABLE_EQUALITY_COMPARISON_NONCE, authchallenge_response.server_hash) + expected_hmac = _hmac_sha256(CRYPTOVARIABLE_EQUALITY_COMPARISON_NONCE, expected_server_hash) + + if authchallenge_hmac != expected_hmac: raise AuthSecurityFailure('Tor provided the wrong server nonce', cookie_path)
try: - client_hash = stem.util.connection._hmac_sha256( + client_hash = _hmac_sha256( CLIENT_HASH_CONSTANT, cookie_data + client_nonce + authchallenge_response.server_nonce)
@@ -1100,6 +1107,19 @@ def _read_cookie(cookie_path, is_safecookie): raise UnreadableCookieFile(exc_msg, cookie_path, is_safecookie)
+def _hmac_sha256(key, msg): + """ + Generates a sha256 digest using the given key and message. + + :param str key: starting key for the hash + :param str msg: message to be hashed + + :returns: sha256 digest of msg as bytes, hashed using the given key + """ + + return hmac.new(key, msg, hashlib.sha256).digest() + + class AuthenticationFailure(Exception): """ Base error for authentication failures. diff --git a/stem/util/connection.py b/stem/util/connection.py index 2ddecd74..c23d74e7 100644 --- a/stem/util/connection.py +++ b/stem/util/connection.py @@ -55,8 +55,6 @@ Connection and networking based utility functions. """
import collections -import hashlib -import hmac import os import platform import re @@ -89,8 +87,6 @@ Resolver = enum.Enum( FULL_IPv4_MASK = '255.255.255.255' FULL_IPv6_MASK = 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF'
-CRYPTOVARIABLE_EQUALITY_COMPARISON_NONCE = os.urandom(32) - PORT_USES = None # port number => description
RESOLVER_COMMAND = { @@ -739,34 +735,6 @@ def _address_to_binary(address): raise ValueError("'%s' is neither an IPv4 or IPv6 address" % address)
-def _hmac_sha256(key, msg): - """ - Generates a sha256 digest using the given key and message. - - :param str key: starting key for the hash - :param str msg: message to be hashed - - :returns: sha256 digest of msg as bytes, hashed using the given key - """ - - return hmac.new(key, msg, hashlib.sha256).digest() - - -def _cryptovariables_equal(x, y): - """ - Compares two strings for equality securely. - - :param str x: string to be compared. - :param str y: the other string to be compared. - - :returns: **True** if both strings are equal, **False** otherwise. - """ - - return ( - _hmac_sha256(CRYPTOVARIABLE_EQUALITY_COMPARISON_NONCE, x) == - _hmac_sha256(CRYPTOVARIABLE_EQUALITY_COMPARISON_NONCE, y)) - - # TODO: drop with stem 2.x # We renamed our methods to drop a redundant 'get_*' prefix, so alias the old # names for backward compatability.