Last active
January 25, 2021 03:05
-
-
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.
This file contains hidden or 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
# 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