Skip to content


Folders and files

Last commit message
Last commit date

Latest commit



31 Commits

Repository files navigation


python-aprmd5 is a Python extension written in C that wraps the MD5 routines of the Apache Portable Runtime (APR) Utility Library (libaprutil) and exposes them to the Python interpreter as the module aprmd5. The main purpose of writing python-aprmd5 in the first place has been to expose the function apr_md5_encode(), which generates salted crypt-style hashes using a version of the MD5 hash algorithm that was modified especially for the APR project.

The resulting hashes always start with the prefix characters $apr1$ in order to distinguish them from the result of various other crypt() variants, which use other prefixes. For instance, for input "foo" and salt "mYJd83wW", apr_md5_encode() produces the following hash:


Hashes like this are typically generated by the command line utility htpasswd, which is part of the Apache HTTP server project. The hashes encrypt user passwords that are used by the Apache HTTP server for basic user authentication.

For completeness sake, python-aprmd5 exposes not only apr_md5_encode() but most of the other functions of libaprutil's MD5 routines as well. Where those functions are concerned with the original, unmodified MD5 algorithm, this is mostly a duplication of effort as that algorithm can be easily obtained through the Python Standard Library module hashlib. In fact I advise against using python-aprmd5 if you are interested in the original MD5 algorithm only.

Release notes

This is python-aprmd5 0.2.1.

Changes in this release:

  • patch for by Juan A. Diaz to auto-detect Mac OS X and Debian
  • the project has moved to GitHub
  • no functional changes

For more details see the ChangeLog document.

Project status

As of version 0.2, I consider python-aprmd5 to be feature complete. Unless a change in libaprutil breaks python-aprmd5, it is therefore rather unlikely that there will ever be a version 0.3. Maintenance releases 0.2.x will occur only if bugs are detected, or if I can be motivated to fix the crappy build process.

License and source code

python-aprmd5 is licensed under the GNU General Public License (GPLv3). You should have received a copy of the license along with the python-aprmd5 module distribution (see the file COPYING inside the distribution). If not, see

The source code for python-aprmd5 can be downloaded from GitHub. The repository includes project files to hack python-aprmd5 in Eclipse using PyDev.


Obviously, python-aprmd5 depends on the presence of libaprutil. At compile time, both the headers and the library file must be present. At runtime, the library file is sufficient.

libaprutil versions

No formal tests for compatibility with certain versions of libaprutil have been performed. The earliest version that I have casually used on my system at home (a Mac OS X box) is libaprutil 0.9. Another version that I have used for casual testing on a Debian virtual box is libaprutil 1.3.5. As the interface of the MD5 routines has not changed for a long time, and even across major versions of libaprutil, it is reasonable to expect that python-aprmd5 will work with pretty much all versions of libaprutil.

See the INSTALL document for details on how to build python-aprmd5 against different versions of libaprutil.

Python versions

python-aprmd5 implements both the 2.x and the 3.x versions of Python's C-API, so in theory it should work with all versions of Python 2.x and 3.x. In practice, no formal tests have been performed to verify this statement. The earliest version of Python that I have used to build python-aprmd5 with has been 2.5.1, and the latest version has been 3.1.1 (both on Mac OS X 10.5).

Limitations and known bugs

On some platforms, password_validate() incorrectly returns True if it is fed with an empty hash, regardless of the password that is being validated. This is probably a bug in the system's crypt() function, exposed by the way how libaprutil calls that function. I have found this behaviour on Debian lenny, the issue is reported at the Debian bugtracker.


Example 1: Usage of apr_md5_encode().

from aprmd5 import md5_encode

password = "foo"
salt = "mYJd83wW"
# result will be "$apr1$mYJd83wW$IO.6aK3G0d4mHxcImhPX50"
result = md5_encode(password, salt)

Example 2: Usage of password_validate().

from aprmd5 import password_validate

password = "foo"
hash = "$apr1$mYJd83wW$IO.6aK3G0d4mHxcImhPX50"
# result will be True
result = password_validate(password, hash)

Example 3: Usage of regular MD5 algorithm. The example uses the b"" notation from Python 3.

from aprmd5 import md5

m1 = md5(b"foo")
m2 = md5()
# result1 and result2 will both be "acbd18db4cc2f85cedef654fccc4a4d8"
result1 = m1.hexdigest()
result2 = m2.hexdigest()


Python interface to the MD5 routines of the Apache Portable Runtime Utility Library (libaprutil). python-aprmd5 is feature complete, hence the low activity.






No packages published