@@ -131,6 +131,35 @@ def _digest(msg, mac=mac):
131
131
_ui ^= from_bytes (_u1 , 'big' )
132
132
return to_bytes (_ui , 20 , 'big' )
133
133
134
+ try :
135
+ from hmac import compare_digest
136
+ except ImportError :
137
+ if PY3 :
138
+ def _xor_bytes (a , b ):
139
+ return a ^ b
140
+ else :
141
+ def _xor_bytes (a , b , _ord = ord ):
142
+ return _ord (a ) ^ _ord (b )
143
+
144
+ # Python 2.x < 2.7.7 and Python 3.x < 3.3
145
+ # References:
146
+ # - http://bugs.python.org/issue14532
147
+ # - http://bugs.python.org/issue14955
148
+ # - http://bugs.python.org/issue15061
149
+ def compare_digest (a , b , _xor_bytes = _xor_bytes ):
150
+ left = None
151
+ right = b
152
+ if len (a ) == len (b ):
153
+ left = a
154
+ result = 0
155
+ if len (a ) != len (b ):
156
+ left = b
157
+ result = 1
158
+
159
+ for x , y in zip (left , right ):
160
+ result |= _xor_bytes (x , y )
161
+ return result == 0
162
+
134
163
135
164
def _parse_scram_response (response ):
136
165
"""Split a scram response into key, value pairs."""
@@ -187,7 +216,7 @@ def _authenticate_scram_sha1(credentials, sock_info):
187
216
res = sock_info .command (source , cmd )
188
217
189
218
parsed = _parse_scram_response (res ['payload' ])
190
- if parsed [b'v' ] != server_sig :
219
+ if not compare_digest ( parsed [b'v' ], server_sig ) :
191
220
raise OperationFailure ("Server returned an invalid signature." )
192
221
193
222
# Depending on how it's configured, Cyrus SASL (which the server uses)
0 commit comments