-
-
Save seansummers/0a13325f4ea7a1a7e6e247771cce80df to your computer and use it in GitHub Desktop.
JWKS parsing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# | |
# openssl asn1parse -noout -out private_key.der -genconf <(python jwks2asn1.py private_key.json) | |
# openssl rsa -in private_key.der -inform der > private_key.pem | |
# | |
# rfc7517.3 : urlsafe_b64decode | |
# rfc7517.A.1 : ints are big-indian | |
# | |
import base64 | |
import dataclasses | |
import json | |
import operator | |
import pathlib | |
import sys | |
@dataclasses.dataclass | |
class Jwks: | |
n: int | |
e: int | |
d: int | |
p: int | |
q: int | |
dp: int | |
dq: int | |
qi: int | |
def __post_init__(self): | |
for field in dataclasses.fields(self): | |
name, type_ = field.name, field.type | |
value = getattr(self, name) | |
if not isinstance(value, type_): | |
if isinstance(value, str): | |
value = base64.urlsafe_b64decode(f"{value}==") | |
if isinstance(value, bytes): | |
value = int.from_bytes(value, byteorder="big") | |
setattr(self, name, type_(value)) | |
@classmethod | |
def from_jwks(cls, jwks_file: pathlib.Path): | |
fields = (_.name for _ in dataclasses.fields(cls)) | |
return cls(*operator.itemgetter(*fields)(json.loads(jwks_file.read_text()))) | |
def asasn1(self): | |
prefix = [ | |
"asn1=SEQUENCE:private_key", | |
"[private_key]", | |
"version=INTEGER:0", | |
] + [ | |
f"{field.name}=INTEGER:0X{getattr(self, field.name):X}" | |
for field in dataclasses.fields(self) | |
] | |
return "\n".join(prefix) | |
print(Jwks.from_jwks(pathlib.Path(sys.argv[1])).asasn1()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# | |
# openssl asn1parse -noout -out private_key.der -genconf <(python tiny_jwks2asn1.py private_key.json) | |
# openssl rsa -in private_key.der -inform der > private_key.pem | |
# | |
# rfc7517.3 : urlsafe_b64decode | |
# rfc7517.A.1 : ints are big-indian | |
# | |
import base64 | |
import json | |
import pathlib | |
import sys | |
asn1_header = ["asn1=SEQUENCE:private_key", "[private_key]", "version=INTEGER:0"] | |
fields = ("n", "e", "d", "p", "q", "dp", "dq", "qi") | |
def parse(value: str) -> int: | |
data = base64.urlsafe_b64decode(f"{value}==") | |
return int.from_bytes(data, byteorder="big") | |
jwks = json.loads(pathlib.Path(sys.argv[1]).read_text()) | |
print( | |
"\n".join( | |
asn1_header + [f"{field}=INTEGER:0X{parse(jwks[field]):X}" for field in fields] | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment