76 lines
1.7 KiB
Lua
76 lines
1.7 KiB
Lua
local Config = require('opus.config')
|
|
local SHA = require('opus.crypto.sha2')
|
|
local Util = require('opus.util')
|
|
|
|
local PBKDF2_ITERATIONS = 100
|
|
|
|
local Security = { }
|
|
|
|
local function generateSalt()
|
|
local salt = { }
|
|
for _ = 1, 16 do
|
|
salt[#salt + 1] = math.random(0, 0xFF)
|
|
end
|
|
return setmetatable(salt, Util.byteArrayMT):toHex()
|
|
end
|
|
|
|
function Security.verifyPassword(password)
|
|
local stored = Security.getPassword()
|
|
if not stored then
|
|
return false
|
|
end
|
|
|
|
-- New format: { hash = hex, salt = hex, iter = N }
|
|
if type(stored) == 'table' and stored.hash and stored.salt then
|
|
local iter = stored.iter or PBKDF2_ITERATIONS
|
|
local derived = SHA.pbkdf2(password, Util.hexToByteArray(stored.salt), iter)
|
|
return derived:toHex() == stored.hash
|
|
end
|
|
|
|
-- Legacy format: plain SHA-256 hex string
|
|
if type(stored) == 'string' then
|
|
return SHA.compute(password) == stored
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function Security.hasPassword()
|
|
return not not Security.getPassword()
|
|
end
|
|
|
|
function Security.getIdentifier()
|
|
local config = Config.load('os')
|
|
|
|
if not config.identifier then
|
|
local key = { }
|
|
for _ = 1, 32 do
|
|
table.insert(key, ("%02x"):format(math.random(0, 0xFF)))
|
|
end
|
|
config.identifier = table.concat(key)
|
|
|
|
Config.update('os', config)
|
|
end
|
|
|
|
return config.identifier
|
|
end
|
|
|
|
function Security.updatePassword(password)
|
|
local salt = generateSalt()
|
|
local derived = SHA.pbkdf2(password, Util.hexToByteArray(salt), PBKDF2_ITERATIONS)
|
|
|
|
local config = Config.load('os')
|
|
config.password = {
|
|
hash = derived:toHex(),
|
|
salt = salt,
|
|
iter = PBKDF2_ITERATIONS,
|
|
}
|
|
Config.update('os', config)
|
|
end
|
|
|
|
function Security.getPassword()
|
|
return Config.load('os').password
|
|
end
|
|
|
|
return Security
|