Skip to content

Commit 9b0f0f1

Browse files
committed
Created utils.py to hold functions like constant_time_compare and base64-encoding
1 parent 1da2d4a commit 9b0f0f1

File tree

3 files changed

+42
-41
lines changed

3 files changed

+42
-41
lines changed

jwt/__init__.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from datetime import datetime, timedelta
1313
from calendar import timegm
1414
from collections import Mapping
15+
from utils import base64url_encode, base64url_decode
1516

1617
from .compat import (json, string_types, text_type, constant_time_compare,
1718
timedelta_total_seconds)
@@ -70,25 +71,11 @@ class InvalidAudienceError(InvalidTokenError):
7071
class InvalidIssuerError(InvalidTokenError):
7172
pass
7273

73-
7474
# Compatibility aliases (deprecated)
7575
ExpiredSignature = ExpiredSignatureError
7676
InvalidAudience = InvalidAudienceError
7777
InvalidIssuer = InvalidIssuerError
7878

79-
def base64url_decode(input):
80-
rem = len(input) % 4
81-
82-
if rem > 0:
83-
input += b'=' * (4 - rem)
84-
85-
return base64.urlsafe_b64decode(input)
86-
87-
88-
def base64url_encode(input):
89-
return base64.urlsafe_b64encode(input).replace(b'=', b'')
90-
91-
9279
def header(jwt):
9380
if isinstance(jwt, text_type):
9481
jwt = jwt.encode('utf-8')

jwt/algorithms.py

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sys
44

55
from jwt import register_algorithm
6+
from utils import constant_time_compare
67

78
if sys.version_info >= (3, 0, 0):
89
unicode = str
@@ -77,33 +78,7 @@ def sign(self, msg, key):
7778
return hmac.new(key, msg, self.hash_alg).digest()
7879

7980
def verify(self, msg, key, sig):
80-
return self._constant_time_compare(sig, self.sign(msg, key))
81-
82-
try:
83-
_constant_time_compare = staticmethod(hmac.compare_digest)
84-
except AttributeError:
85-
# Fallback for Python < 2.7.7 and Python < 3.3
86-
@staticmethod
87-
def constant_time_compare(val1, val2):
88-
"""
89-
Returns True if the two strings are equal, False otherwise.
90-
91-
The time taken is independent of the number of characters that match.
92-
"""
93-
if len(val1) != len(val2):
94-
return False
95-
96-
result = 0
97-
98-
if sys.version_info >= (3, 0, 0):
99-
# Bytes are numbers
100-
for x, y in zip(val1, val2):
101-
result |= x ^ y
102-
else:
103-
for x, y in zip(val1, val2):
104-
result |= ord(x) ^ ord(y)
105-
106-
return result == 0
81+
return constant_time_compare(sig, self.sign(msg, key))
10782

10883
if has_crypto:
10984

jwt/utils.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import base64
2+
import hmac
3+
4+
def base64url_decode(input):
5+
rem = len(input) % 4
6+
7+
if rem > 0:
8+
input += b'=' * (4 - rem)
9+
10+
return base64.urlsafe_b64decode(input)
11+
12+
13+
def base64url_encode(input):
14+
return base64.urlsafe_b64encode(input).replace(b'=', b'')
15+
16+
try:
17+
constant_time_compare = hmac.compare_digest
18+
except AttributeError:
19+
# Fallback for Python < 2.7.7 and Python < 3.3
20+
def constant_time_compare(val1, val2):
21+
"""
22+
Returns True if the two strings are equal, False otherwise.
23+
24+
The time taken is independent of the number of characters that match.
25+
"""
26+
if len(val1) != len(val2):
27+
return False
28+
29+
result = 0
30+
31+
if sys.version_info >= (3, 0, 0):
32+
# Bytes are numbers
33+
for x, y in zip(val1, val2):
34+
result |= x ^ y
35+
else:
36+
for x, y in zip(val1, val2):
37+
result |= ord(x) ^ ord(y)
38+
39+
return result == 0

0 commit comments

Comments
 (0)