Skip to content

Instantly share code, notes, and snippets.

@paoneJP
Created December 21, 2014 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paoneJP/7fa72ab0458091681b30 to your computer and use it in GitHub Desktop.
Save paoneJP/7fa72ab0458091681b30 to your computer and use it in GitHub Desktop.
Parsing a JWE Example which is described in draft-ietf-jose-json-web-encryption Appendix A.2 (RSA1_5 and A128CBC-HS256)
from base64 import urlsafe_b64decode
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Cipher import AES
from Crypto.Hash import HMAC
from Crypto.Hash import SHA256
from Crypto.Util.number import long_to_bytes, bytes_to_long
# RSA Key described in A.2.3
#
jwk_n = 'sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl' \
'UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre' \
'cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_' \
'7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI' \
'Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU' \
'7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw'
jwk_e = 'AQAB'
jwk_d = 'VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq' \
'1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry' \
'nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_' \
'0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj' \
'-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj' \
'T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ'
jwk_p = '9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68' \
'ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP' \
'krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM'
jwk_q = 'uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y' \
'BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN' \
'-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0'
n = bytes_to_long(urlsafe_b64decode(jwk_n+'=='))
e = bytes_to_long(urlsafe_b64decode(jwk_e+'=='))
d = bytes_to_long(urlsafe_b64decode(jwk_d+'=='))
p = bytes_to_long(urlsafe_b64decode(jwk_p+'=='))
q = bytes_to_long(urlsafe_b64decode(jwk_q+'=='))
key = RSA.construct((n, e, d, p, q))
# Target JWT described in A.2.7
#
jwt = 'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.' \
'UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm' \
'1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7Pc' \
'HALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIF' \
'NPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8' \
'rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv' \
'-B3oWh2TbqmScqXMR4gp_A.' \
'AxY8DCtDaGlsbGljb3RoZQ.' \
'KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.' \
'9hH0vgRfYgPnAHOd8stkvw'.split('.')
# Decode JOSE Header (JWE Protected Header) [A.2.1]
#
header = urlsafe_b64decode(jwt[0]+'==').decode()
print('## JOSE Header\n', header)
# Decrypt CEK usign the RSAES-PKCS1-V1_5 algorithm [A.2.3][A.2.2]
#
cek = PKCS1_v1_5.new(key).decrypt(urlsafe_b64decode(jwt[1]+'=='), None)
print('## CEK\n', list(cek))
# Decode Initializtion Vector [A.2.4][B.4]
#
iv = urlsafe_b64decode(jwt[2]+'==')
print('## IV\n', list(iv))
# Decode Additional Authenticated Data (use JWE Protected Header) [A.2.5]
#
aad = jwt[0].encode()
print('## AAD\n', list(aad))
# Extract MAC_KEY and ENC_KEY [B.1]
#
mac_key = cek[:16]
enc_key = cek[16:]
print('## MAC_KEY\n', list(mac_key))
print('## ENC_KEY\n', list(enc_key))
# Decrypt Ciphertext [B.2]
## Decode Ciphertext
ct = urlsafe_b64decode(jwt[3]+'==')
print('## Ciphertext\n', list(ct))
## Decrypt Ciphertext
aes = AES.new(enc_key, AES.MODE_CBC, iv)
text = aes.decrypt(ct).decode()
## Remove PKCS#7 padding
for n in range(1, aes.block_size+1):
padding = chr(n) * n
if text.endswith(padding):
text = text[:-n]
print('## Plaintext\n', text)
# AAD Length value [B.3]
#
al = long_to_bytes(len(aad)*8, 8)
print('## AL value\n', list(al))
# Input to HMAC Computation [B.5]
#
print('## Input to HMAC Computation (AAD + IV + Ciphertext + AL value)\n',
list(aad+iv+ct+al))
# Compute HMAC Value [B.6]
#
m = HMAC.new(mac_key, aad+iv+ct+al, SHA256).digest()
print('## Computed HMAC Value\n', list(m))
# Compute Authentication Tag [B.7]
#
t = m[:16]
tag = urlsafe_b64decode(jwt[4]+'==')
print('## Computed Authentiction Tag\n', list(t))
print('## Authentication Tag in JWT\n', list(tag))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment