Skip to content

Commit d11b756

Browse files
authored
Merge pull request #40 from QuantumBA/update_dependencies
⬆️ Upgraded JWT
2 parents 04543d4 + 84a81b5 commit d11b756

2 files changed

Lines changed: 30 additions & 22 deletions

File tree

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22
name = "pyverless"
3-
version = "0.0.56"
4-
authors = ["rperez <rperez@op2aim.io>"]
3+
version = "0.0.57"
4+
authors = ["foqum <info@foqum.io>"]
55
description="A mini-framework providing tools to help you make complex APIs with serverless"
66
readme="README.md"
77
license="BSD"
@@ -10,7 +10,7 @@ classifiers=[
1010
# 3 - Alpha
1111
# 4 - Beta
1212
# 5 - Production/Stable
13-
"Development Status :: 3 - Alpha",
13+
"Development Status :: 4 - Beta",
1414
# Indicate who your project is intended for
1515
"Intended Audience :: Developers",
1616
"Topic :: Software Development :: Build Tools",
@@ -29,7 +29,7 @@ repository = "https://github.com/QuantumBA/pyverless"
2929

3030
[tool.poetry.dependencies]
3131
python = "^3.8"
32-
PyJWT = "<2.0.0"
32+
PyJWT = ">2.0.0"
3333
PyYAML = ">=5.1"
3434
sentry-sdk = ">=0.5.1"
3535
python-json-logger = ">=2.0.7"

pyverless/crypto.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import base64
2-
from calendar import timegm
32
import hashlib
43
import hmac
5-
import jwt
64
import random
75
import time
6+
from calendar import timegm
87
from datetime import datetime
98

10-
from pyverless.exceptions import Unauthorized
9+
import jwt
10+
1111
from pyverless.config import settings
12+
from pyverless.exceptions import Unauthorized
1213

1314

1415
def get_json_web_token(payload, expires=True, expiry=settings.JWT_EXPIRY):
@@ -19,17 +20,22 @@ def get_json_web_token(payload, expires=True, expiry=settings.JWT_EXPIRY):
1920
# This is how PyJwt computes now, check:
2021
# https://github.com/jpadilla/pyjwt/blob/master/jwt/api_jwt.py#L153
2122
now = timegm(datetime.utcnow().utctimetuple())
22-
payload['exp'] = now + int(expiry)
23+
payload["exp"] = now + int(expiry)
2324

24-
return jwt.encode(payload, settings.SECRET_KEY, settings.JWT_ALGORITHM).decode('utf-8')
25+
return jwt.encode(payload, settings.SECRET_KEY, settings.JWT_ALGORITHM)
2526

2627

2728
def decode_json_web_token(token, leeway=settings.JWT_LEEWAY):
2829
"""
2930
Decode a JWT. Leeway time may be provided.
3031
"""
3132
try:
32-
decoded = jwt.decode(token, settings.SECRET_KEY, leeway=leeway, algorithms=[settings.JWT_ALGORITHM])
33+
decoded = jwt.decode(
34+
token,
35+
settings.SECRET_KEY,
36+
leeway=leeway,
37+
algorithms=[settings.JWT_ALGORITHM],
38+
)
3339
except jwt.exceptions.DecodeError:
3440
raise Unauthorized()
3541
except jwt.exceptions.ExpiredSignatureError:
@@ -52,26 +58,27 @@ def is_expired(expiry):
5258
# and it can be found here:
5359
# https://github.com/django/django/blob/master/django/contrib/auth/hashers.py
5460
# https://github.com/django/django/blob/master/django/utils/crypto.py
55-
def get_random_string(length=12,
56-
allowed_chars='abcdefghijklmnopqrstuvwxyz'
57-
'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'):
61+
def get_random_string(
62+
length=12,
63+
allowed_chars="abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
64+
):
5865
"""
5966
Return a securely generated random string.
6067
The default length of 12 with the a-z, A-Z, 0-9 character set returns
6168
a 71-bit value. log_2((26+26+10)^12) =~ 71 bits
6269
"""
6370
random.seed(
6471
hashlib.sha256(
65-
('%s%s%s' % (random.getstate(), time.time(), settings.SECRET_KEY)).encode()
72+
("%s%s%s" % (random.getstate(), time.time(), settings.SECRET_KEY)).encode()
6673
).digest()
6774
)
68-
return ''.join(random.choice(allowed_chars) for i in range(length))
75+
return "".join(random.choice(allowed_chars) for i in range(length))
6976

7077

7178
def constant_time_compare(val1, val2):
7279
"""Return True if the two strings are equal, False otherwise."""
73-
val1 = val1.encode('utf-8', 'strict')
74-
val2 = val2.encode('utf-8', 'strict')
80+
val1 = val1.encode("utf-8", "strict")
81+
val2 = val2.encode("utf-8", "strict")
7582
return hmac.compare_digest(val1, val2)
7683

7784

@@ -81,18 +88,19 @@ def pbkdf2(password, salt, iterations, dklen=0, digest=None):
8188
digest = hashlib.sha256
8289
if not dklen:
8390
dklen = None
84-
password = password.encode('utf-8', 'strict')
85-
salt = salt.encode('utf-8', 'strict')
91+
password = password.encode("utf-8", "strict")
92+
salt = salt.encode("utf-8", "strict")
8693
return hashlib.pbkdf2_hmac(digest().name, password, salt, iterations, dklen)
8794

8895

89-
class PBKDF2PasswordHasher():
96+
class PBKDF2PasswordHasher:
9097
"""
9198
Secure password hashing using the PBKDF2 algorithm (recommended)
9299
Configured to use PBKDF2 + HMAC + SHA256.
93100
The result is a 64 byte binary string. Iterations may be changed
94101
safely but you must rename the algorithm if you change SHA256.
95102
"""
103+
96104
algorithm = "pbkdf2_sha256"
97105
iterations = 100000
98106
digest = hashlib.sha256
@@ -105,11 +113,11 @@ def encode(self, password, salt=None, iterations=None):
105113
iterations = self.iterations
106114

107115
hash = pbkdf2(password, salt, iterations, digest=self.digest)
108-
hash = base64.b64encode(hash).decode('ascii').strip()
116+
hash = base64.b64encode(hash).decode("ascii").strip()
109117
return "%s$%d$%s$%s" % (self.algorithm, iterations, salt, hash)
110118

111119
def verify(self, password, encoded):
112-
algorithm, iterations, salt, hash = encoded.split('$', 3)
120+
algorithm, iterations, salt, hash = encoded.split("$", 3)
113121
assert algorithm == self.algorithm
114122
encoded_2 = self.encode(password, salt, int(iterations))
115123
return constant_time_compare(encoded, encoded_2)

0 commit comments

Comments
 (0)