htpasswd encrypts passwords using either bcrypt, a version of MD5 modified for Apache, SHA1, or the system's crypt() routine. Files managed by htpasswd may contain a mixture of different encoding types of passwords; some user records may have bcrypt or MD5-encrypted passwords while others in the same file may have passwords encrypted with crypt().
I tried using either openssl::md5 or digest::digest, but they don't seem to be producing anything I can recognise.
Here's some sample output using htpasswd on Ubuntu. The result changes each time, presumably because there is a salt being used. The hash doesn't look like it's base64-encoded either.
hongo@hongsdev:~$ echo bar | htpasswd -n -i foo
foo:$apr1$ArTUhiJz$/qjciBNKHEWwpXBof75rb.
hongo@hongsdev:~$ echo bar | htpasswd -n -i foo
foo:$apr1$pZxmtIam$VkfMvV2qR4NBkPm3MKcJ/.
hongo@hongsdev:~$ echo bar | htpasswd -n -i foo
foo:$apr1$IFM43G9p$UkQB9QSONrwD74WpXlP7f/
Some attempts using openssl::md5 and digest::digest:
Are you open to using the reticulate package to access Python functionality?
There exists a python library htpasswd that I was able to install on Windows, but this depends on some linux-specific encryption requirements, so I couldn't get it to work.
However, the error message pointed me to Using the crypt module in Windows?, where an alternative python library passlib is recommended.
Hi Andrie, I'm trying to avoid pulling in big dependencies as much as possible. I mean, I could just install apache2 and call htpasswd directly, but I'd much rather have a lightweight solution.
One problem is that password hashing is more involved than just calculating the hash of the password. Another problem is that Apache uses a special version of MD5 encrypted passwords: $apr1$ instead of $1$ as magic constant, which enters the actual hash calculation, c.f. this perl implementation. It might be possible to implement this in R with packages like openssl and digest, but I have not tried that. I would probably try to reuse the actual C implementation via one of these routes:
Try to get htpasswd without a full httpd. On Debian (and derived like Ubuntu) you can get htpasswd via the rather light-weight apache2-utils package.
The actual hashing functions can be found in the APR library. On Debian (and derived) one could install libapr1-devel and write a small R package (possibly using Rcpp) that provides bindings for the relevant functions.
The hashing functions are only a small part of the APR library. One could copy the relevant files (e.g. apr_md5.c) into an R package and provide bindings for the relevant functions (possibly using Rcpp).