114 lines
2.5 KiB
Go
114 lines
2.5 KiB
Go
package runner
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
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 !state.IsString(1) {
|
|
state.PushString("password_hash error: expected string password")
|
|
return 1
|
|
}
|
|
|
|
password := state.ToString(1)
|
|
|
|
params := &argon2id.Params{
|
|
Memory: 64 * 1024,
|
|
Iterations: 3,
|
|
Parallelism: 4,
|
|
SaltLength: 16,
|
|
KeyLength: 32,
|
|
}
|
|
|
|
if state.IsTable(2) {
|
|
state.GetField(2, "memory")
|
|
if state.IsNumber(-1) {
|
|
params.Memory = uint32(state.ToNumber(-1))
|
|
if params.Memory < 8*1024 {
|
|
params.Memory = 8 * 1024 // Minimum 8MB
|
|
}
|
|
}
|
|
state.Pop(1)
|
|
|
|
state.GetField(2, "iterations")
|
|
if state.IsNumber(-1) {
|
|
params.Iterations = uint32(state.ToNumber(-1))
|
|
if params.Iterations < 1 {
|
|
params.Iterations = 1 // Minimum 1 iteration
|
|
}
|
|
}
|
|
state.Pop(1)
|
|
|
|
state.GetField(2, "parallelism")
|
|
if state.IsNumber(-1) {
|
|
params.Parallelism = uint8(state.ToNumber(-1))
|
|
if params.Parallelism < 1 {
|
|
params.Parallelism = 1 // Minimum 1 thread
|
|
}
|
|
}
|
|
state.Pop(1)
|
|
|
|
state.GetField(2, "salt_length")
|
|
if state.IsNumber(-1) {
|
|
params.SaltLength = uint32(state.ToNumber(-1))
|
|
if params.SaltLength < 8 {
|
|
params.SaltLength = 8 // Minimum 8 bytes
|
|
}
|
|
}
|
|
state.Pop(1)
|
|
|
|
state.GetField(2, "key_length")
|
|
if state.IsNumber(-1) {
|
|
params.KeyLength = uint32(state.ToNumber(-1))
|
|
if params.KeyLength < 16 {
|
|
params.KeyLength = 16 // Minimum 16 bytes
|
|
}
|
|
}
|
|
state.Pop(1)
|
|
}
|
|
|
|
hash, err := argon2id.CreateHash(password, params)
|
|
if err != nil {
|
|
state.PushString(fmt.Sprintf("password_hash error: %v", err))
|
|
return 1
|
|
}
|
|
|
|
state.PushString(hash)
|
|
return 1
|
|
}
|
|
|
|
// passwordVerify verifies a password against a hash
|
|
func passwordVerify(state *luajit.State) int {
|
|
if !state.IsString(1) || !state.IsString(2) {
|
|
state.PushBoolean(false)
|
|
return 1
|
|
}
|
|
|
|
password := state.ToString(1)
|
|
hash := state.ToString(2)
|
|
|
|
match, err := argon2id.ComparePasswordAndHash(password, hash)
|
|
if err != nil {
|
|
state.PushBoolean(false)
|
|
return 1
|
|
}
|
|
|
|
state.PushBoolean(match)
|
|
return 1
|
|
}
|