98 lines
2.4 KiB
Go
98 lines
2.4 KiB
Go
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
|
|
}
|