# Using Mathematica how can I simulate the MD5 or SHA encryption of a userid and password performed by htpasswd on Apache?

htpasswd hashes a user's password using the userid. Thus this generator takes both userid and password as inputs and then it outputs a line for inclusion in the .htpasswd file. For example using the inputs "test" (userid) and "hello" (password), I got test:$apr1$ftcMHGnd\$ZBAuErXOcG9n4PH9vGLFe/, ready for pasting into .htpasswd.

How can I simulate this using Mathematica?

The best I've got at the moment is

Hash["a-string-here", "MD5"] ,


which takes only a single input and outputs in decimal.

• According to this, you would need to use "an Apache-specific algorithm using an iterated (1,000 times) MD5 digest of various combinations of a random 32-bit salt and the password. See the APR source file apr_md5.c for the details of the algorithm." Oct 21 '17 at 18:53
• You can run the htpasswd command line tool from within Mathematica and get the encrypted passwords that way, if this is of interest. Oct 21 '17 at 19:11
• The hash doesn't have to be the same as one produced by htpasswd, just so long as it validates. Can this not be done with Hash in Mathematica, so long as one can pass it the right input that combines userid and password?
– user51827
Oct 21 '17 at 21:56
• Their SHA scheme is much easier to generate, e.g. StringJoin[userid, "{SHA}", DeveloperEncodeBase64[FromCharacterCode[IntegerDigits[Hash[password, "SHA"], 256]]]] Oct 22 '17 at 3:24
• Thanks, @ilian . SHA will do me fine. I will edit the question to say MD5 or SHA and will then accept your answer.
– user51827
Oct 22 '17 at 10:06

According to this, the MD5 scheme uses "an Apache-specific algorithm using an iterated (1,000 times) MD5 digest of various combinations of a random 32-bit salt and the password. See the APR source file apr_md5.c for the details of the algorithm."

While that could in principle be implemented, it's much easier to generate the SHA1-digest form:

htpasswdsha[userid_?StringQ, password_?StringQ] := StringJoin[userid, ":{SHA}",
DeveloperEncodeBase64[FromCharacterCode[IntegerDigits[Hash[password, "SHA"], 256, 20]]]]


For example,

htpasswdsha["myName", "myPassword"]

(* "myName:{SHA}VBPuJHI7uixaa6LQGWx4s+5GKNE=" *)


Instead of DeveloperEncodeBase64 one could use the documented ExportString[str, "Base64"] but that seems to add an extra newline ("\n") character at the end.

The same function can be written in a much simpler way with the recently released version 11.3.0, using only BaseEncode and Hash:

htpasswdsha[userid_?StringQ, password_?StringQ] :=
StringJoin[userid, ":{SHA}", BaseEncode[Hash[password, "SHA", "ByteArray"]]]
`