Skip to content


Subversion checkout URL

You can clone with
Download ZIP
A bcrypt library for Lua
C Assembly Lua Makefile
Latest commit d64cdc8 @mikejsavage Add v2.1 rockspec
Failed to load latest commit information.
compat whoops
include Remove stray header
rockspec Add v2.1 rockspec
src Bump year
.gitignore Rewrite!
Makefile Compile compat/safebfuns.c with -O0
Makefile.mess Use -lrt on Linux
Makefile.obsd Rewrite! Add licensing info
test-chroot.lua Rewrite!
test-digest.lua Rewrite!
tune.lua Rewrite!

A Lua wrapper for OpenBSD's bcrypt.


lua >= 5.1


Many of the files in this repository have been taken from OpenBSD's tree. You should consult individual file headers for specific licensing information. More broadly, everything here is compatible with the ISC license.


$ luarocks install bcrypt


local bcrypt = require( "bcrypt" )

-- Bigger numbers here will make your digest exponentially harder to compute
local log_rounds = 9

local digest = bcrypt.digest( "password", log_rounds )
assert( bcrypt.verify( "password", digest ) )

Security concerns

Lua will keep plaintext passwords around in memory as part of its string interning mechanism. As far as I'm aware, there's nothing I can do about this.


If you would like to automatically tune the number of rounds to your hardware, you can include a function like:

function bcrypt.tune( t )
    local SAMPLES = 10
    local rounds = 5

    while true do
        local total = 0

        for i = 1, SAMPLES do
            local start = os.clock()
            bcrypt.digest( "asdf", rounds )
            local delta = os.clock() - start

            total = total + delta

        if ( total / SAMPLES ) * 1000 >= t then
            return rounds - 1

        rounds = rounds + 1

This function returns the largest load factor such that bcrypt.digest( str, work ) takes less than t milliseconds (assuming your CPU isn't dodgy).

Note that this will take at least 2 * SAMPLES * t ms to evaluate.


Some operating systems do not provide a method for reliably getting random data from inside a chroot. One workaround for this is to chroot after initialising lua-bcrypt, for example by using lua-setuid.

local setuid = require( "setuid" )
local bcrypt = require( "bcrypt" )

assert( setuid.chroot( "." ) )
assert( not "/etc/passwd", "r" ) )

print( bcrypt.digest( "adsf", 5 ) )

There are also operating system specific workarounds. On non-bleeding-edge (earlier than 3.17) Linux kernels, you can run:

mkdir /path/to/chroot/dev
mknod -m 644 /path/to/chroot/dev/urandom c 1 9

I have included a test script in test-chroot.lua.

Something went wrong with that request. Please try again.