Skip to content

Instantly share code, notes, and snippets.

@MadMartian
Last active March 21, 2022 19:35
Show Gist options
  • Save MadMartian/984afe43fbbfc3b16f9a5992c8363908 to your computer and use it in GitHub Desktop.
Save MadMartian/984afe43fbbfc3b16f9a5992c8363908 to your computer and use it in GitHub Desktop.
Python script to decode SHC-encoded JWTs generated by SmartHealth Cards.
#!/usr/bin/env python3
from sys import stdin, stdout, stderr
import base64
import re
import zlib
import argparse
ap = argparse.ArgumentParser()
ap.add_argument('--header', action='store_true', help='Output the JWT header instead of the payload')
args = ap.parse_args()
def b64dec(data):
nipad = len(data) % 4
if nipad > 0:
data += "=" * (4 - nipad)
return base64.urlsafe_b64decode(data)
def readSHC():
result = ""
while True:
n = stdin.read(2)
if not n:
break
try:
n = int(n) + 45
result += chr(n)
except ValueError:
pass
return result
scheme = stdin.read(5)
if scheme != "shc:/":
print("Input is not in SHC scheme format", file = stderr)
sys.exit(1)
result = readSHC()
m = re.match("^([\w\d\.\-_]+)\.([\w\d\.\-_]+)\.([\w\d\.\-_]+)$", result)
if m:
parts = m.groups()
else:
print("Encoded SHC is not a valid JWT", file = stderr)
sys.exit(2)
if args.header:
header = b64dec(parts[0]).decode('utf-8')
print (header)
else:
payload = b64dec(parts[1])
payload = zlib.decompress(payload, wbits = -15)
payload = payload.decode("utf-8")
print (payload)
@MadMartian
Copy link
Author

MadMartian commented Mar 21, 2022

Basic Usage Instructions

  • Use zbarimg to decode the QR code
  • Strip the junk (QR-Code...)
  • Pipe it into shc-jwt.py
  • Pipe that into yq

Example: zbarimg path-to-qrcode.jpg | sed 's/^QR-Code://' | shc-jwt.py | yq -y .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment