local rand = require 'openssl.rand' local hmac = require 'openssl.hmac' local function xor(a, b) local x = {} for i = 1, #b do x[i] = string.char(a:byte(i) ~ b:byte(i)) end return table.concat(x) end local function prf(algo, password, salt, iter) local k local prev = salt for i = 1, iter do local h = hmac.new(password, algo) local sum = h:final(prev) k = k and xor(k, sum) or sum prev = sum end return k end return function(password, salt, algo, iter, blocks) local salt = salt or rand.bytes(256) local algo = algo or 'sha3-512' local iter = iter or 10000 local blocks = blocks or 1 local dk = "" for i = 1, blocks do dk = dk .. prf(algo, password, salt..(('>I4'):pack(i)), iter) end return dk, salt, algo, iter, blocks end