package runner import ( luajit "git.sharkk.net/Sky/LuaJIT-to-Go" "github.com/alexedwards/argon2id" ) // RegisterPasswordFunctions registers password-related functions in the Lua state func RegisterPasswordFunctions(state *luajit.State) error { if err := state.RegisterGoFunction("__password_hash", passwordHash); err != nil { return err } if err := state.RegisterGoFunction("__password_verify", passwordVerify); err != nil { return err } return nil } // passwordHash implements the Argon2id password hashing using alexedwards/argon2id func passwordHash(state *luajit.State) int { if err := state.CheckMinArgs(1); err != nil { return state.PushError("password_hash: %v", err) } password, err := state.SafeToString(1) if err != nil { return state.PushError("password_hash: password must be string") } params := &argon2id.Params{ Memory: 128 * 1024, Iterations: 4, Parallelism: 4, SaltLength: 16, KeyLength: 32, } if state.GetTop() >= 2 && state.IsTable(2) { // Use new field getters with validation if memory := state.GetFieldNumber(2, "memory", 0); memory > 0 { params.Memory = max(uint32(memory), 8*1024) } if iterations := state.GetFieldNumber(2, "iterations", 0); iterations > 0 { params.Iterations = max(uint32(iterations), 1) } if parallelism := state.GetFieldNumber(2, "parallelism", 0); parallelism > 0 { params.Parallelism = max(uint8(parallelism), 1) } if saltLength := state.GetFieldNumber(2, "salt_length", 0); saltLength > 0 { params.SaltLength = max(uint32(saltLength), 8) } if keyLength := state.GetFieldNumber(2, "key_length", 0); keyLength > 0 { params.KeyLength = max(uint32(keyLength), 16) } } hash, err := argon2id.CreateHash(password, params) if err != nil { return state.PushError("password_hash: %v", err) } state.PushString(hash) return 1 } // passwordVerify verifies a password against a hash func passwordVerify(state *luajit.State) int { if err := state.CheckExactArgs(2); err != nil { state.PushBoolean(false) return 1 } password, err := state.SafeToString(1) if err != nil { state.PushBoolean(false) return 1 } hash, err := state.SafeToString(2) if err != nil { state.PushBoolean(false) return 1 } match, err := argon2id.ComparePasswordAndHash(password, hash) if err != nil { state.PushBoolean(false) return 1 } state.PushBoolean(match) return 1 }