Last active
March 4, 2018 21:23
-
-
Save joernheissler/04d9dcfb3a99e318871e451c9043f2dc to your computer and use it in GitHub Desktop.
Test program to dump + verify JWS
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 | |
data0 = """ | |
{ | |
"payload": "eyJjb250YWN0IjpbIm1haWx0bzphZG1pbkBleGFtcGxlLm5ldCJdLCJ0 | |
ZXJtc09mU2VydmljZUFncmVlZCI6dHJ1ZX0", | |
"protected": "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eS | |
I6IkVDIiwieCI6ImY0T2tsNnZhZEFiS1pDN2NWd0tNc1RCd1Z0dDRm | |
YlFDMWI1emJ3azFTUmciLCJ5IjoiblVtV0pmQVZpOG0wVy1rdEhnM3 | |
VZS3pJWS1vUFdRcFB4bHhCVTRVLURLbyJ9LCJub25jZSI6IkFtTmpu | |
cUp2Vlc3Y3dEalJ5SlJXQldrYkZ2X1lneWQwU1o4bENOYXkzdTgiLC | |
J1cmwiOiJodHRwczovL2V4YW1wbGUuY29tL2FjbWUvbmV3LWFjY291 | |
bnQifQ", | |
"signature": "RzIgePMgHF74on3-8-pzxliZRKl-a7ba_fCKqUS53RghGtj5hnhauJ | |
OgPzY1BxPDPTKiEMVrjKXJroPuZWYybg" | |
} | |
""" | |
data1 = """ | |
{ | |
"payload": "eyJwYXlsb2FkIjoiZXlKaFkyTnZkVzUwSWpvaWFIUjBjSE02THk5bGVH | |
RnRjR3hsTG1OdmJTOWhZMjFsTDJGalkzUXZNVEl6TkRVaUxDSnVaWGRM | |
WlhraU9uc2lZM0oySWpvaVVDMHlOVFlpTENKcmRIa2lPaUpGUXlJc0lu | |
Z2lPaUpmVVcxTmMxZG1RVVpCVGpBMWEwVnZYekI2WTNJM1IzWnpaMG94 | |
VkVkSU1uVlJaR1IwV1RSS2NYTkZJaXdpZVNJNklrSk5Na0ZNU2tGTmFV | |
aHBkM0pWVUVOMWNUbHZUbFpNZFhCclowNUVSR0pLUTJaUVIzRXlVbDlW | |
YVVraWZYMCIsInByb3RlY3RlZCI6ImV5SmhiR2NpT2lKRlV6STFOaUlz | |
SW1wM2F5STZleUpqY25ZaU9pSlFMVEkxTmlJc0ltdDBlU0k2SWtWRElp | |
d2llQ0k2SWw5UmJVMXpWMlpCUmtGT01EVnJSVzlmTUhwamNqZEhkbk5u | |
U2pGVVIwZ3lkVkZrWkhSWk5FcHhjMFVpTENKNUlqb2lRazB5UVV4S1FV | |
MXBTR2wzY2xWUVEzVnhPVzlPVmt4MWNHdG5Ua1JFWWtwRFpsQkhjVEpT | |
WDFWcFNTSjlMQ0oxY213aU9pSm9kSFJ3Y3pvdkwyVjRZVzF3YkdVdVky | |
OXRMMkZqYldVdmEyVjVMV05vWVc1blpTSjkiLCJzaWduYXR1cmUiOiJn | |
LThkVUtHM1dRVTh5bWJZaXJWellkZTVPUEVyT3o1NkZmRWJlS2MyaDVV | |
d2R5VzJMeEd2VXlzcnRtd1pId1JyZTBRbFhteVlwMlk5SWN2R3FrREta | |
ZyJ9", | |
"protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6Imh0dHBzOi8vZXhhbXBsZS5jb2 | |
0vYWNtZS9hY2N0LzEyMzQ1Iiwibm9uY2UiOiJKUFF0by1RX1RNVENs | |
bmhHdjBERXA0ajk1b2RITGp6Qkp6LS1nR0lnZHBJIiwidXJsIjoiaH | |
R0cHM6Ly9leGFtcGxlLmNvbS9hY21lL2tleS1jaGFuZ2UifQ", | |
"signature": "C7ZkQahUwcw1orQh5RPNtWVQmytnnYTnH4VgGxt2Yq807lSealPnqR | |
jTBxvpfo_ceuaFj0G1fp-g_o4ZmjkFBg" | |
} | |
""" | |
import re | |
import json | |
import base64 | |
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicNumbers, SECP256R1, ECDSA | |
from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature | |
from cryptography.hazmat.backends import default_backend | |
from cryptography.hazmat.primitives import hashes | |
def unwrap(data): | |
return json.loads(re.sub(r'\s+(?=[-_a-zA-Z0-9])', '', data)) | |
def b64dec(data): | |
return base64.urlsafe_b64decode((data + '=' * (-len(data) % 4))) | |
def bytes_to_int(b): | |
return int.from_bytes(b, 'big') | |
def b64_to_int(data): | |
return bytes_to_int(b64dec(data)) | |
def dump_jws(data, pub=None): | |
protected = json.loads(b64dec(data['protected'])) | |
print("Protected:") | |
print(json.dumps(protected, indent=4, sort_keys=True)) | |
print() | |
if protected['alg'] != 'ES256': | |
raise ValueError('Not supported') | |
if not pub: | |
if protected['jwk']['crv'] != 'P-256': | |
raise ValueError('Not supported') | |
if protected['jwk']['kty'] != 'EC': | |
raise ValueError('Not supported') | |
pub = EllipticCurvePublicNumbers( | |
b64_to_int(protected['jwk']['x']), b64_to_int(protected['jwk']['y']), SECP256R1() | |
).public_key(default_backend()) | |
sig = b64dec(data['signature']) | |
if len(sig) != 64: | |
raise ValueError('Bad length') | |
sig = encode_dss_signature(bytes_to_int(sig[:32]), bytes_to_int(sig[32:])) | |
msg = (data['protected'] + '.' + data['payload']).encode() | |
pub.verify(sig, msg, ECDSA(hashes.SHA256())) | |
payload = json.loads(b64dec(data['payload'])) | |
print("Payload:") | |
print(json.dumps(payload, indent=4, sort_keys=True)) | |
print() | |
return pub, payload | |
pub0, create_acc = dump_jws(unwrap(data0)) | |
print("-----\n") | |
pub0, key_change_outer = dump_jws(unwrap(data1), pub0) | |
print("-----\n") | |
pub1, key_change_inner = dump_jws(key_change_outer) |
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
Protected: | |
{ | |
"alg": "ES256", | |
"jwk": { | |
"crv": "P-256", | |
"kty": "EC", | |
"x": "f4Okl6vadAbKZC7cVwKMsTBwVtt4fbQC1b5zbwk1SRg", | |
"y": "nUmWJfAVi8m0W-ktHg3uYKzIY-oPWQpPxlxBU4U-DKo" | |
}, | |
"nonce": "AmNjnqJvVW7cwDjRyJRWBWkbFv_Ygyd0SZ8lCNay3u8", | |
"url": "https://example.com/acme/new-account" | |
} | |
Payload: | |
{ | |
"contact": [ | |
"mailto:admin@example.net" | |
], | |
"termsOfServiceAgreed": true | |
} | |
----- | |
Protected: | |
{ | |
"alg": "ES256", | |
"kid": "https://example.com/acme/acct/12345", | |
"nonce": "JPQto-Q_TMTClnhGv0DEp4j95odHLjzBJz--gGIgdpI", | |
"url": "https://example.com/acme/key-change" | |
} | |
Payload: | |
{ | |
"payload": "eyJhY2NvdW50IjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9hY21lL2FjY3QvMTIzNDUiLCJuZXdLZXkiOnsiY3J2IjoiUC0yNTYiLCJrdHkiOiJFQyIsIngiOiJfUW1Nc1dmQUZBTjA1a0VvXzB6Y3I3R3ZzZ0oxVEdIMnVRZGR0WTRKcXNFIiwieSI6IkJNMkFMSkFNaUhpd3JVUEN1cTlvTlZMdXBrZ05ERGJKQ2ZQR3EyUl9VaUkifX0", | |
"protected": "eyJhbGciOiJFUzI1NiIsImp3ayI6eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6Il9RbU1zV2ZBRkFOMDVrRW9fMHpjcjdHdnNnSjFUR0gydVFkZHRZNEpxc0UiLCJ5IjoiQk0yQUxKQU1pSGl3clVQQ3VxOW9OVkx1cGtnTkREYkpDZlBHcTJSX1VpSSJ9LCJ1cmwiOiJodHRwczovL2V4YW1wbGUuY29tL2FjbWUva2V5LWNoYW5nZSJ9", | |
"signature": "g-8dUKG3WQU8ymbYirVzYde5OPErOz56FfEbeKc2h5UwdyW2LxGvUysrtmwZHwRre0QlXmyYp2Y9IcvGqkDKZg" | |
} | |
----- | |
Protected: | |
{ | |
"alg": "ES256", | |
"jwk": { | |
"crv": "P-256", | |
"kty": "EC", | |
"x": "_QmMsWfAFAN05kEo_0zcr7GvsgJ1TGH2uQddtY4JqsE", | |
"y": "BM2ALJAMiHiwrUPCuq9oNVLupkgNDDbJCfPGq2R_UiI" | |
}, | |
"url": "https://example.com/acme/key-change" | |
} | |
Payload: | |
{ | |
"account": "https://example.com/acme/acct/12345", | |
"newKey": { | |
"crv": "P-256", | |
"kty": "EC", | |
"x": "_QmMsWfAFAN05kEo_0zcr7GvsgJ1TGH2uQddtY4JqsE", | |
"y": "BM2ALJAMiHiwrUPCuq9oNVLupkgNDDbJCfPGq2R_UiI" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment