Skip to content

Commit 6e36194

Browse files
committed
Useful when you want to look at a signed/encrypted/signed+encrypted JWT.
If signed and no verification keys available the script will just dump the payload.
1 parent 38ac0e3 commit 6e36194

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed

src/cryptojwt/tools/jwtpeek.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#!/usr/bin/env python3
2+
3+
# Thanks to @rohe Roland Hedberg for most of the lines in this script :).
4+
5+
import argparse
6+
import json
7+
import os
8+
import sys
9+
10+
from pygments import highlight
11+
from pygments.formatters.terminal import TerminalFormatter
12+
from pygments.lexers.data import JsonLexer
13+
14+
from cryptojwt.jwe import jwe
15+
from cryptojwt.jwk.hmac import SYMKey
16+
from cryptojwt.jwk.jwk import key_from_jwk_dict
17+
from cryptojwt.jwk.rsa import RSAKey
18+
from cryptojwt.jwk.rsa import import_rsa_key
19+
from cryptojwt.jws import jws
20+
from cryptojwt.key_bundle import KeyBundle
21+
from cryptojwt.key_jar import KeyJar
22+
23+
__author__ = 'roland'
24+
25+
"""
26+
Tool to view, verify signature on and/or decrypt JSON Web Token.
27+
28+
Usage examples:
29+
30+
(1) read JWT from stdin, no keys
31+
32+
cat idtoken | ./jwtpeek.py -f -
33+
34+
or
35+
36+
cat idtoken | ./jwtpeek.py
37+
38+
(2) read JWT from file, use keys from file with a JWKS to verify/decrypt
39+
40+
./jwtpeek.py -f idtoken -J keys.jwks
41+
42+
or
43+
44+
(3) JWT from stdin, no keys
45+
46+
echo json.web.token | ./jwtpeek.py
47+
48+
"""
49+
50+
51+
def main(jwt, keys, quiet):
52+
_jw = jwe.factory(jwt)
53+
if _jw:
54+
if not quiet:
55+
print("Encrypted JSON Web Token")
56+
print('Headers: {}'.format(_jw.jwt.headers))
57+
if keys:
58+
res = _jw.decrypt(keys=keys)
59+
json_object = json.loads(res)
60+
json_str = json.dumps(json_object, indent=2)
61+
print(highlight(json_str, JsonLexer(), TerminalFormatter()))
62+
else:
63+
print("No keys can't decrypt")
64+
sys.exit(1)
65+
else:
66+
_jw = jws.factory(jwt)
67+
if _jw:
68+
if quiet:
69+
json_object = json.loads(_jw.jwt.part[1].decode("utf-8"))
70+
json_str = json.dumps(json_object, indent=2)
71+
print(highlight(json_str, JsonLexer(), TerminalFormatter()))
72+
else:
73+
print("Signed JSON Web Token")
74+
print('Headers: {}'.format(_jw.jwt.headers))
75+
if keys:
76+
res = _jw.verify_compact(keys=keys)
77+
print('Verified message: {}'.format(res))
78+
else:
79+
json_object = json.loads(_jw.jwt.part[1].decode("utf-8"))
80+
json_str = json.dumps(json_object, indent=2)
81+
print('Unverified message: {}'.format(
82+
highlight(json_str, JsonLexer(), TerminalFormatter())))
83+
84+
85+
if __name__ == "__main__":
86+
parser = argparse.ArgumentParser()
87+
parser.add_argument('-r', dest="rsa_file",
88+
help="File containing a RSA key")
89+
parser.add_argument('-k', dest="hmac_key",
90+
help="If using a HMAC algorithm this is the key")
91+
parser.add_argument('-i', dest="kid", help="key id")
92+
parser.add_argument('-j', dest="jwk", help="JSON Web Key")
93+
parser.add_argument('-J', dest="jwks", help="JSON Web Keys")
94+
parser.add_argument('-u', dest="jwks_url", help="JSON Web Keys URL")
95+
parser.add_argument('-f', dest="msg", help="The message")
96+
parser.add_argument('-q', dest="quiet",
97+
help="Quiet mode -- only show the RAW but prettified JSON",
98+
action='store_true')
99+
100+
args = parser.parse_args()
101+
102+
if args.kid:
103+
_kid = args.kid
104+
else:
105+
_kid = ''
106+
107+
keys = []
108+
if args.rsa_file:
109+
keys.append(RSAKey(key=import_rsa_key(args.rsa_file), kid=_kid))
110+
if args.hmac_key:
111+
keys.append(SYMKey(key=args.hmac_key, kid=_kid))
112+
113+
if args.jwk:
114+
_key = key_from_jwk_dict(open(args.jwk).read())
115+
keys.append(_key)
116+
117+
if args.jwks:
118+
_k = KeyJar()
119+
_k.import_jwks(open(args.jwks).read(), "")
120+
keys.extend(_k.issuer_keys(""))
121+
122+
if args.jwks_url:
123+
_kb = KeyBundle(source=args.jwks_url)
124+
keys.extend(_kb.get())
125+
126+
if not args.msg: # If nothing specified assume stdin
127+
message = sys.stdin.read()
128+
elif args.msg == "-":
129+
message = sys.stdin.read()
130+
else:
131+
if os.path.isfile(args.msg):
132+
message = open(args.msg).read().strip("\n")
133+
else:
134+
message = args.msg
135+
136+
message = message.strip()
137+
message = message.strip('"')
138+
main(message, keys, args.quiet)

0 commit comments

Comments
 (0)