Skip to content

Instantly share code, notes, and snippets.

@jaames
Last active January 25, 2021 03:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaames/3330842d5c5fb22ca7d6c63d90a3378b to your computer and use it in GitHub Desktop.
Save jaames/3330842d5c5fb22ca7d6c63d90a3378b to your computer and use it in GitHub Desktop.
resign a kwz for flipnote studio 3d. handles signature and all crc32 checksums.
# usage: python3 kwzSignature.py <privkey.pem> <target.kwz>
# rsa module installed with:
# pip3 install rsa
# documentation here:
# https://stuvel.eu/files/python-rsa-doc/usage.html
import struct
import rsa
import zlib
from sys import argv
with open(argv[1], "rb") as pem, open(argv[2], "rb+") as flipnote:
key = rsa.PrivateKey.load_pkcs1(pem.read())
flipnote.seek(0, 2)
body_length = flipnote.tell() - 256
flipnote.seek(0)
offset = 0
while offset < body_length:
flipnote.seek(offset)
magic, length = struct.unpack("<3sxI", flipnote.read(8))
magic = str(magic, "utf-8")
if magic in ["KFH", "KTN", "KMC"]:
flipnote.seek(4, 1)
content = flipnote.read(length - 4)
checksum = zlib.crc32(content)
flipnote.seek(-length, 1)
flipnote.write(struct.pack("<I", checksum))
if magic == "KSN":
# skip section header + sound meta
flipnote.seek(offset + 8 + 28)
# read content excluding meta
content = flipnote.read(length - 28)
# recalc checksum
flipnote.seek(offset + 8 + 24)
checksum = zlib.crc32(content)
flipnote.write(struct.pack("<I", checksum))
offset += length + 8
flipnote.seek(0)
body = flipnote.read(body_length)
signature = rsa.sign(body, key, "SHA-256")
flipnote.write(signature)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment