Using opus 4.7 to translate libhonoka into lua
Find a file
2026-05-16 12:30:06 -05:00
honoka2.lua Initial commit. Pure Lua port of libhonoka. 2026-05-16 12:30:06 -05:00
honokamiku.lua Initial commit. Pure Lua port of libhonoka. 2026-05-16 12:30:06 -05:00
honokamiku_keys.lua Initial commit. Pure Lua port of libhonoka. 2026-05-16 12:30:06 -05:00
LICENSE.md Initial commit. Pure Lua port of libhonoka. 2026-05-16 12:30:06 -05:00
md5.lua Initial commit. Pure Lua port of libhonoka. 2026-05-16 12:30:06 -05:00
README.md Initial commit. Pure Lua port of libhonoka. 2026-05-16 12:30:06 -05:00

libhonoka-lua

Pure Lua port of libhonoka, the improved HonokaMiku implementation for decrypting/encrypting Love Live! School Idol Festival game files.

Implements V1 through V6 encryption/decryption for the SIF EN, JP, TW, and CN clients, plus custom prefix / key-table support.

Requirements

  • Lua 5.2 (uses the bit32 library).

No external dependencies — the MD5 implementation is included.

Files

File Purpose
honokamiku.lua The library. require("honokamiku").
honokamiku_keys.lua V3 key tables (JP/EN/TW/CN) and LCG parameters.
md5.lua MD5 implementation used by the library.
honoka2.lua Command-line front-end, mirrors the upstream honoka2 binary.

Library usage

local hm = require("honokamiku")

-- Decrypt a SIF EN file:
local ctx = hm.new_context()
local f = io.open("encrypted.bin", "rb")
local first4 = f:read(4)

local gid = hm.decrypt_init_auto(ctx, "filename.bin", first4)
assert(gid ~= hm.GAMEFILE_UNKNOWN)

if hm.decrypt_is_final_init(ctx) then
    local next12 = f:read(12)
    assert(hm.decrypt_final_init(ctx, gid, nil, -1, "filename.bin", next12)
        == hm.ERR_OK)
end

local out = {}
while true do
    local chunk = f:read(4096)
    if not chunk or #chunk == 0 then break end
    out[#out + 1] = hm.decrypt_block(ctx, chunk)
end
f:close()
-- table.concat(out) is the decrypted payload.

Encryption:

local ctx = hm.new_context()
local err, header = hm.encrypt_init(
    ctx, hm.MODE_V3, hm.GAMEFILE_EN,
    nil, nil, -1, "filename.bin"
)
assert(err == hm.ERR_OK)
-- Write `header` to the output, then feed plaintext through hm.decrypt_block.

CLI usage

lua honoka2.lua [options] <input file> [output file]

Same flag set as the upstream C binary:

Flag Meaning
-w / -j / -t / -c SIF EN / JP / TW / CN
-w1 ... -w6 Force algorithm version 1..6 for that game
-e Encrypt instead of decrypt
-d Detect-only (print the file's gamefile + version)
-b <name> Override the basename used in the key derivation
-x / -p <prefix> / -k <keytable> / -s <namesum> Custom game file
-h / -? Show usage
-v Show version
-l Show license (project + MD5 RSA notice)

Examples:

# Auto-detect SIF region and version:
lua honoka2.lua encrypted.bin decrypted.bin

# Encrypt a file as SIF JP V5:
lua honoka2.lua -e -j5 -b "filename.bin" plain.bin encrypted.bin

# Pipe via stdin/stdout (basename must be set explicitly):
cat encrypted.bin | lua honoka2.lua -w3 -b "filename.bin" - > decrypted.bin

License

MIT (see LICENSE.md). The bundled MD5 implementation is derived from the RSA Data Security, Inc. MD5 Message Digest Algorithm; its license notice is also reproduced in LICENSE.md and must be retained.