I’ve tried to brute force every possible evp in the roEvpCipher object, but none was able to decrypt the payload. First, i try to decrypt the simmetric key passing the private key and initialization vector, forming a list of every decrypted simmetric key. And then, with every assembled key i try to decrypt the payload. Here is the code:
evpList = ["bf-cbc","bf","bf-cfb","bf-ecb","bf-ofb","des-cbc","des","des-cfb","des-ecb","des-ofb","des-ede-cbc",
"des-ede","des-ede-cfb","des-ede-ofb","des-ede3-cbc","des-ede3","des3","des-ede3-cfb","des-ede3-ofb","desx","desx-cbc", "aes-256-cbc", "aes-256", "aes-256-cfb", "aes-256-cfb1", "aes-256-cfb8", "aes-256-ecb", "aes-256-ofb","aes-192-cbc", "aes-192", "aes-192-cfb", "aes-192-cfb1", "aes-192-cfb8", "aes-192-ecb", "aes-192-ofb","aes-128-cbc", "aes-128", "aes-128-cfb", "aes-128-cfb1", "aes-128-cfb8", "aes-128-ecb", "aes-128-ofb"]
jwe = "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.j1RBCCV2E6YRUD_RI1oPtQLNDjg2tWELjNit29PzUrSvwx060YcKeg.OJecPTIfpng9qZCIJh2-3g.AOYr-AJ_AqDgx7HjzNFPaiDJjhmQCMkwDX31bQO1Rh_Ui2MI3PECVow28Ym2RrUG6jxrUeSGA1Q6G_RdVk1P9-Op4NIFm26XgYx5dq57LXY9-9Be0WaRGq2HvXNFeb-LpmC1UjQ2BDReTwHynOrg98ETjz8j1XQunHSlmdhT1A42_PRsUTo1yyi7kRtIshPSXUlfxZA0hFubnJf2KQWy_hU42b01UUcBnuPEza6Ne_Y2Et-_qmGNRQDDj34R0afXRiByWJJ8YoUNAZrmVydvFEASYMIvB7HQE1dB8QfFhabfipA875bDi98ix5jdPprELykBnwG9KpOZS1RS1hfXBjKuZDuu7PKQdDbDmxe0CtwdA6mWkohDpqX1UeRdVqmcQZs906z0bQ3CvaOdHCx4dSMDRJIflIwsfw3PkzENSEpHLfOJVdi-CabE0iBeGjgcuffkEDqEf2llSj-wqiIfzwn9kyWH_8_rVWwWX6TTWSbaGIMWcxGgRogVKiusYCqqYFtQmtQc6SwkJOARkHQkscZGV9YE1wCQNl_ZtgD6QfRJRHYRU_LOMCb3HKrFyeyIlSfjFMDS5vY1nP5xWOZLqU_ELLMOOEeyBCWzJMwH-t-NMpg8NlUnK5mrcGlIVGmlSdQd1rh1GyfZGQHW6AmQvNSDOMydX-AM_r1ZkuLt3q5yvu6iwKphbZwFz4b9-CgxOGAKH2MI7pAeJHXbaklDisSNZyMJ1MIkyl8sxBQpe9DZRG1WXN1ySYJ4obOaqNahX9tz8-5a3uWscinI016gOQK3zG1dUx43ta3-Q6E7QOlV1SWYSAmrR-bTLT4q2BafWYuhNsR-9_9SYkAHUEFO6hu9yXqvkpbLV7HBz4m-nMQ-iBmrnhSdm1UZRxZQjJOpcaLEEscfD5h6FuliPCE0fdxMge6QM9emsGczonQ2CD2zlgMSHg_PX1VQ98wQy0H6tZBEHiReNTU7_ezUg_YR-ocfgvcQj2h0orvy62gNLL_4Ro2sU8dft0KRVeLF4qInrcnS2gUEs0Gjv-y3zFZ30XLPIGUxe7W5dkB4v1w7V3Ogvw6X8p8je3oMUyUXFlUr6e-TUf-C8PBFXazHaLDzyRCvqXHfFihaPx0bMGQ4V3H3RvmMG4I6wejoOXXIHzp8gmFLmUqV7j4P6Qop_h96icaT0SBXFLt_BZVcUXbuNrkeOEeDvs2w9DE14vTAja-qMn6VMEpZ1h573xtt6o-BIM9hJIdHxfH6qTFtFPINR5lYBfpek2Ljw6pFO3_yXPz1Vgqv2snX8cZ-SSykeefeoMTuyZVpoSEp0VJm6B89oPG6qOjnh6TSWJGvCAQo6Op-fcKhErMAwZc5DBcm1lwTny8K9HUmShiXYvnPr8FAmPxbYOOiVUJkfAHeyqoQ5F06PHjVqaslyuAS4O-gHuYnlhk1kMe32xZKkuKm5eBdxDSAQzASO9exhNQr-l8g4IXzOALZ_pzRJTOcCPsnhgH7XE-N8tyfKjrFMcHCDQvmpDVMf4UIAJUcULNPhVCx7B3rbhrd0lHnDLetwUDh_ytMq6NazQe8sIWDBJBLjB_IGrtUba532gFzMI3cZ0Vxr_2O_Mm2lWzRW9AmE4m3yP6VSeGBo8jCGlsqacKMM2RMalcbQuU8qD8e2XSJl_D2jigzpSYIQTYm0hOfTA7-g6I6Yfp1hwC5q_gU1RUBgxzA8WMzIEVxFqGWr-0Q8JQ_xiCsHE5KUMwnCWL1m8SSDFayw97bAo8o4vNr_wdUBZE9EQ4NU0FGYKyaSHEnSghNgB-RI7t723V7xaiyg78xwkcX39XQBZlvg7gp68_Cq34lK04gBnboZTREYGgNNak5O0V1D-077JXlaNOKqHcPGLcnAQyk_gweT1_U9oOrcOf1IVRXr6ke4Kzgc-KypowR80Cui5KY4L9rxlTPBTY15KxMaNo_uo0FP46WobeYzALcZuw81duDfXgJbqESyjmwx4R44orAr3xU2vjNBIgvfzWbwOW0_93Kr8AvRyqYrsJZfI9XDTAnmklKW-1QNgYljOiBESLCAY1_ueiCYYgT70jn9ADhmw6IFOrcGAFoKnwtgAhnHuc-_gg0ZpghJwhmPYbs5ZQhFthC6U55JixnkroDOfxTnxoGion4dX7d1svAiX5IfeuvoiXHJxNAysj4GuVgQctLsVwVUuDMvznTKwIFfmUl3AKuq1QPZz2EhWfpab632JoGWiVQvCVBwLlW3rBnN1AvJlMPpOydTie2Q1AC7d69QYEGpZQxWCk9H3TgaXh9Jf5ESGqexQEk8UjLALHDdAwZ8Lo_vnaQzIs0vAVDr6EJkjTQ1K9wVAMV5kEgSomAoIYwd4tw4K-hvRjrV38MEbv92DeRSVKsZIcjmfuxao-ymJJoKwD_cHxeH_REKIPyXTOknveP-d0pimW17mQO_-dYqZnPJZYhlVl61yDPbrmNaVcH4VaaWU8vqtQkydYiBTUd_HoF55xGZtGScc7FMOnbpVrGu7mYN6ShZH7FEZ2BY4pw_Iu2NrHxA99zUtSZTIeUgg4AUscGJH8V9C46jch7G1cGGHJZ0Qf2Dms97F2eOlGzVjMo1BuO15KL9gFXesA6_Ezk0KhLQP-UQZRvfwrmuxS0D0HhxHzJx4NunuZXuKTTM3OFHNxp0NoMoHw8dMXvfUWu2WcSs5ibz7KC_ioY9tew8-IyBn2ADrAlr5Eyb5StjD-IZn_xyVCP0X5rtxRpzGXStwWoOsi7D6k4HaqJFMlS5hv6T22OeuXFo09v5JC27225XpykBWdx8ondYIve72eCL6xlq9XguHUOPDNs9PD9zvFbDzH7YDpRUXOYwGNS3fP2zOEMDNtFL1nzv5wzUaWkyNt1q1ocBbYIq_kK-3iCpoYSh3ecQJdCKI6OTBtt5Ec8TaIguI2Ir7RY6L5JZXbhZBzZ6Uc430Bwba4I_c_DhewJzyj_GeNKjNNy7R5kCCWjyZ30l6rdshXl1kthne7R1TUXA9TKwKJhTiilSWMt0k31iCaZuZDVnjDHE6JN-yCIzI17qB5MjgrzAOwATGRbkvTtkF_X2lNjF1tPs9lSH0AVOP8UW50gL-0MNGimnK-qH6Lj4dD7Mxk4V-PeOyDuNxesKnRXohgaJcq4Hj5BtcIEw_0mQ5yAHBgWkPgEusAPh6c66F90ugBTrYdSbgbKAoQI1irZ4Fj8sAgbqkzRKNP-ZE1ChlfmePCPMohANWWT6z3L8jdLuULRTpwNtHOZ3H0O2qKXJZiu2_QdBnrl9P25FMHuZ3V7ZntFMod32gtIeXn-VpA9v-A2feZv6KXlsc7GakEroWpnTpR_2kLlIXfMVdSYEbzsyeXclQuzAOJqbX-tCwM_Y4_t_J30yh3pgyRRQR0St-IG54bA663x01BDg3XWaBF7VTcj3ztQOFUKeVKRy5ta3qmpREcVYo2jzIqbwPx0InvGzJT2SMgk2L4mMgMiFZIViMzOc7ywjTCBNruDjlMVho7jZgMt_lfFSblSPdr0Z2Vt-nhTNA_QUikWoJxFfAmZ2w.fsvwXsfwYGiuNLsoMTB-Vw"
jweArray = jwe.split(".")
decryptedKeyList = []
for each evp in evpList
privateKeyBa = CreateObject("roByteArray")
enkba = CreateObject("roByteArray")
ivba = CreateObject("roByteArray")
privateKey = "q2nj7sc1m30as24m4nf1mnv[]q981.,a"
enk = jweArray[1]
iv = jweArray[2]
enk = base64UrlToBase64(enk)
iv = base64UrlToBase64(iv)
privateKeyBa.fromAsciiString(privateKey)
enkba.fromBase64String(enk)
ivba.fromBase64String(iv)
pkHex = uCase(privateKeyBa.toHexString())
ivHex = uCase(ivba.toHexString())
cipher = CreateObject("roEvpCipher")
setupResult = cipher.setup(false, evp,pkHex, ivHex, 0)
if setupResult = 0
decryptedKey = cipher.process(enkba)
if(decryptedKey <> invalid)
decryptedKeyList.push(decryptedKey)
end if
end if
end for
for each key in decryptedKeyList
for each evp in evpList
payloadBa = CreateObject("roByteArray")
newKey = CreateObject("roByteArray")
newKey.append(key)
payload = jweArray[3]
payload = lCase(base64UrlToBase64(payload))
payloadBa.fromBase64String(payload)
cipher = CreateObject("roEvpCipher")
setupResult = cipher.setup(false, evp, uCase(newKey.toHexString()), "", 0)
if setupResult = 0
decryptedPayload = cipher.process(payloadBa)
if decryptedPayload <> invalid
? decryptedPayload.toAsciiString()
end if
end if
end for
end for
I’ve tried to decrypt the jwe using a public lib like jose and it was able to perform the job without a sweat. Am i missing something? Has anyone done something similar before? Maybe roku does not have support for this key unwrap algorithm. If that’s the case, building one from scratch would be too much troublesome. Maybe the solution would be to request for a new endpoint to the backend team that uses an algorithm roku supports.