Boris Nagaev · Home page | About | Contact | Github | Code | FBB files

Phpass password hashing for Lua

phpass (pronounced “pH pass”) is a portable public domain password hashing framework for use in PHP applications. phpass has been integrated into WordPress 2.5+, bbPress, Vanilla, PivotX 2.1.0+, Chyrp, Textpattern 4.4.0+, and concrete5 5.6.3+.

Lua module lua-phpass implements a subset of phpass (iterated MD5). It’s sufficient to create and check a password hash compatible with portable phpass hash, e.g. a password from wordpress database. Blowfish-based bcrypt and BSDI-style extended DES-based hashes are not supported.

This module is distributed under terms of the MIT License.


$ luarocks install phpass



The code was tested against Lua 5.1, 5.2, 5.3 and LuaJIT 2.0, 2.1.

LuaCrypto for Lua 5.3 requires the following patch:

diff --git a/src/lcrypto.c b/src/lcrypto.c
index 48364d1..e5a62c4 100644
--- a/src/lcrypto.c
+++ b/src/lcrypto.c
@@ -968,7 +968,7 @@ static int verify_fverify(lua_State *L)
 static int rand_do_bytes(lua_State *L, int (*bytes)(unsigned char *, int))
-    size_t count = (size_t)luaL_checkint(L, 1);
+    size_t count = (size_t)luaL_checkinteger(L, 1);
     unsigned char tmp[256], *buf = tmp;
     if (count > sizeof tmp)
         buf = (unsigned char *)malloc(count);

I have applied this patch to my fork of LuaCrypto. There is also the modified version of rockspec for version 0.3.2, which installs modified LuaCrypto.


phpass = require 'phpass'

password = 'test12345'

hash = phpass.hashPassword(password)
--> "$P$EYyDnrNHtS2MG5vTVkvXD6wMnd0C/N/"

phpass.checkPassword(password, hash) --> true
phpass.checkPassword('other password', hash) --> false


Python-phpass, python implementation of phpass was used as a reference.

The algorithm used in phpass.hashPassword generates random salt, so this function returns different hashes for a password.

phpass.hashPassword has second argument, count_log2, which is log2 of number of iterations. The algorithm of hashing is as follows:

count = 2 ^ count_log2
salt = ...
hash = md5(salt .. password)
for i = 1, count do
    hash = md5(hash .. password)