Skip to content

Instantly share code, notes, and snippets.

@jkmartindale
Created March 18, 2024 07:40
Show Gist options
  • Save jkmartindale/6a3b81e5baed5c8eb766a8b65374b3cb to your computer and use it in GitHub Desktop.
Save jkmartindale/6a3b81e5baed5c8eb766a8b65374b3cb to your computer and use it in GitHub Desktop.
Decrypt Hulu SAMI (.smi) subtitles
# Don't use this, just grab WebVTT subtitles instead loool
# This was just how I spent a lazy Sunday evening
from Crypto.Cipher import AES
from Crypto.Util import Padding
import binascii
import glob
import os
from xml.etree import ElementTree
KEY = binascii.unhexlify("4878B22E76379B55C962B18DDBC188D82299F8F52E3E698D0FAF29A40ED64B21")
IV = b"WA7hap7AGUkevuth"
DIRECTORY = "decrypted"
if not os.path.exists(DIRECTORY):
os.makedirs(DIRECTORY)
for file in glob.glob("*.smi"):
tree = ElementTree.parse(file)
encrypted_syncs = tree.findall(".//*[@Encrypted='true']")
if len(encrypted_syncs) == 0:
continue
for sync in encrypted_syncs:
cipher = AES.new(KEY, AES.MODE_CBC, IV)
ciphertext = binascii.unhexlify(sync.text.strip())
plaintext = Padding.unpad(cipher.decrypt(ciphertext), AES.block_size).decode()
subtree = ElementTree.fromstring(plaintext)
sync.text = None
sync.append(subtree)
sync.attrib.pop("Encrypted", None)
tree.write(os.path.join(DIRECTORY, file), encoding="unicode", short_empty_elements=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment