Skip to content

Commit 0bbdfc5

Browse files
python-ecosys/ujwt: Add ujwt module.
1 parent 70e422d commit 0bbdfc5

File tree

5 files changed

+137
-3
lines changed

5 files changed

+137
-3
lines changed

python-ecosys/ujwt/metadata.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
srctype = micropython-lib
2+
type = module
3+
version = 0.1.0

python-ecosys/ujwt/setup.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import sys
2+
3+
# Remove current dir from sys.path, otherwise setuptools will peek up our
4+
# module instead of system's.
5+
sys.path.pop(0)
6+
from setuptools import setup
7+
8+
sys.path.append("..")
9+
import sdist_upip
10+
11+
setup(
12+
name="micropython-ujwt",
13+
version="0.1",
14+
description="ujwt module for MicroPython",
15+
long_description="This is a module reimplemented specifically for MicroPython standard library,\nwith efficient and lean design in mind. Note that this module is likely work\nin progress and likely supports just a subset of CPython's corresponding\nmodule. Please help with the development if you are interested in this\nmodule.",
16+
url="https://github.com/micropython/micropython-lib",
17+
author="micropython-lib Developers",
18+
author_email="micro-python@googlegroups.com",
19+
maintainer="micropython-lib Developers",
20+
maintainer_email="micro-python@googlegroups.com",
21+
license="MIT",
22+
cmdclass={"sdist": sdist_upip.sdist},
23+
py_modules=["ujwt"],
24+
install_requires=["micropython-hmac"],
25+
)

python-ecosys/ujwt/test_ujwt.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import ujwt
2+
from time import time
3+
4+
secret_key = "top-secret!"
5+
6+
jwt = ujwt.encode({"user": "joe"}, secret_key)
7+
decoded = ujwt.decode(jwt, secret_key)
8+
if decoded != {"user": "joe"}:
9+
raise Exception("Invalid decoded JWT")
10+
else:
11+
print("Encode/decode test: OK")
12+
13+
try:
14+
decoded = ujwt.decode(jwt, "wrong-secret")
15+
except ujwt.exceptions.InvalidSignatureError:
16+
print("Invalid signature test: OK")
17+
else:
18+
raise Exception("Invalid JWT should have failed decoding")
19+
20+
jwt = ujwt.encode({"user": "joe", "exp": time() - 1}, secret_key)
21+
try:
22+
decoded = ujwt.decode(jwt, secret_key)
23+
except ujwt.exceptions.ExpiredTokenError:
24+
print("Expired token test: OK")
25+
else:
26+
raise Exception("Expired JWT should have failed decoding")

python-ecosys/ujwt/ujwt.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import binascii
2+
import hashlib
3+
import hmac
4+
import json
5+
from time import time
6+
7+
8+
def _to_b64url(data):
9+
return (
10+
binascii.b2a_base64(data)
11+
.rstrip(b"\n")
12+
.rstrip(b"=")
13+
.replace(b"+", b"-")
14+
.replace(b"/", b"_")
15+
)
16+
17+
18+
def _from_b64url(data):
19+
return binascii.a2b_base64(data.replace(b"-", b"+").replace(b"_", b"/") + b"===")
20+
21+
22+
class exceptions:
23+
class PyJWTError(Exception):
24+
pass
25+
26+
class InvalidTokenError(PyJWTError):
27+
pass
28+
29+
class InvalidAlgorithmError(PyJWTError):
30+
pass
31+
32+
class InvalidSignatureError(PyJWTError):
33+
pass
34+
35+
class ExpiredTokenError(PyJWTError):
36+
pass
37+
38+
39+
def encode(payload, key, algorithm="HS256"):
40+
if algorithm != "HS256":
41+
raise exceptions.InvalidAlgorithmError()
42+
43+
if isinstance(key, str):
44+
key = key.encode()
45+
header = _to_b64url(json.dumps({"typ": "JWT", "alg": algorithm}).encode())
46+
payload = _to_b64url(json.dumps(payload).encode())
47+
signature = _to_b64url(hmac.new(key, header + b"." + payload, hashlib.sha256).digest())
48+
return (header + b"." + payload + b"." + signature).decode()
49+
50+
51+
def decode(token, key, algorithms=["HS256"]):
52+
if "HS256" not in algorithms:
53+
raise exceptions.InvalidAlgorithmError()
54+
55+
parts = token.encode().split(b".")
56+
if len(parts) != 3:
57+
raise exceptions.InvalidTokenError()
58+
59+
try:
60+
header = json.loads(_from_b64url(parts[0]).decode())
61+
payload = json.loads(_from_b64url(parts[1]).decode())
62+
signature = _from_b64url(parts[2])
63+
except Exception:
64+
raise exceptions.InvalidTokenError()
65+
66+
if header["alg"] not in algorithms or header["alg"] != "HS256":
67+
raise exceptions.InvalidAlgorithmError()
68+
69+
if isinstance(key, str):
70+
key = key.encode()
71+
calculated_signature = hmac.new(key, parts[0] + b"." + parts[1], hashlib.sha256).digest()
72+
if signature != calculated_signature:
73+
raise exceptions.InvalidSignatureError()
74+
75+
if "exp" in payload:
76+
if time() > payload["exp"]:
77+
raise exceptions.ExpiredTokenError()
78+
79+
return payload

python-stdlib/hashlib/hashlib/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
def init():
88
for i in ("sha1", "sha224", "sha256", "sha384", "sha512"):
9-
c = getattr(uhashlib, i, None)
10-
if not c:
9+
try:
1110
c = __import__("_" + i, None, None, (), 1)
12-
c = getattr(c, i)
11+
except ImportError:
12+
c = uhashlib
13+
c = getattr(c, i, None)
1314
globals()[i] = c
1415

1516

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy