Can you convert the output of php crypt() to valid MD5?
-
I have some strings that have been encrypted using the http://php.net/crypt. The outputs look something like this: $1$Vf/.4.1.$CgCo33ebiHVuFhpwS.kMI0 $1$84..vD4.$Ps1PdaLWRoaiWDKCfjLyV1 $1$or1.RY4.$v3xo04v1yfB7JxDj1sC/J/ While I believe crypt() is using the MD5 algorithm, the outputs are not valid MD5 hashes. Is there a way of converting the produced hashes into valid MD5 hashes (16-byte hex values)? Update: Thanks for the replies so answers so far. I'm pretty sure the crypt function used is using some sort of MD5 algorithm. What I'm looking to do is convert the ouput that I have into an MD5 hash that looks something like the following: 9e107d9d372bb6826bd81d3542a419d6 e4d909c290d0fb1ca068ffaddf22cbd0 d41d8cd98f00b204e9800998ecf8427e (taken from http://en.wikipedia.org/wiki/MD5) Is there a way of converting from the hashes I have to ones like the above?
-
Answer:
OK, so maybe this answer is a year late, but I'll give it a shot. In your own answer, you note that crypt() is using the FreeBSD MD5, which also does some interesting transformations on the salt before running the hash, so the result of what I'm about to give you will never quite match up with the results of a call to md5(). That said, the only difference between the output you are seeing and the format you are used to is that the output you are seeing is encoded as follows $1$ # this indicates that it is MD5 Vf/.4.1. # these eight characters are the significant portion of the salt $ # this character is technically part of the salt, but it is ignored CgCo33eb # the last 22 characters are the actual hash iHVuFhpw # they are base64 encoded (to be printable) using crypt's alphabet S.kMI0 # floor(22 * 6 / 8) = 16 (the length in bytes of a raw MD5 hash) To my knowledge, the alphabet used by crypt looks like this: ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz So, with all of this borne in mind, here is how you can convert the 22 character crypt-base64 hash into a 32 character base16 (hexadecimal) hash: First, you need something to convert the base64 (with custom alphabet) into a raw 16-byte MD5 hash. define('CRYPT_ALPHA','./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'); /** * Decodes a base64 string based on the alphabet set in constant CRYPT_ALPHA * Uses string functions rather than binary transformations, because said * transformations aren't really much faster in PHP * @params string $str The string to decode * @return string The raw output, which may include unprintable characters */ function base64_decode_ex($str) { // set up the array to feed numerical data using characters as keys $alpha = array_flip(str_split(CRYPT_ALPHA)); // split the input into single-character (6 bit) chunks $bitArray = str_split($str); $decodedStr = ''; foreach ($bitArray as &$bits) { if ($bits == '$') { // $ indicates the end of the string, to stop processing here break; } if (!isset($alpha[$bits])) { // if we encounter a character not in the alphabet return false; // then break execution, the string is invalid } // decbin will only return significant digits, so use sprintf to pad to 6 bits $decodedStr .= sprintf('%06s', decbin($alpha[$bits])); } // there can be up to 6 unused bits at the end of a string, so discard them $decodedStr = substr($decodedStr, 0, strlen($decodedStr) - (strlen($decodedStr) % 8)); $byteArray = str_split($decodedStr, 8); foreach ($byteArray as &$byte) { $byte = chr(bindec($byte)); } return join($byteArray); } Now that you've got the raw data, you'll need a method to convert it to the base-16 format you're expecting, which couldn't be easier. /** * Takes an input in base 256 and encodes it to base 16 using the Hex alphabet * This function will not be commented. For more info: * @see http://php.net/str-split * @see http://php.net/sprintf * * @param string $str The value to convert * @return string The base 16 rendering */ function base16_encode($str) { $byteArray = str_split($str); foreach ($byteArray as &$byte) { $byte = sprintf('%02x', ord($byte)); } return join($byteArray); } Finally, since the output of crypt includes a lot of data we don't need (and, in fact, cannot use) for this process, a short and sweet function to not only tie these two together but to allow for direct input of output from crypt. /** * Takes a 22 byte crypt-base-64 hash and converts it to base 16 * If the input is longer than 22 chars (e.g., the entire output of crypt()), * then this function will strip all but the last 22. Fails if under 22 chars * * @param string $hash The hash to convert * @param string The equivalent base16 hash (therefore a number) */ function md5_b64tob16($hash) { if (strlen($hash) < 22) { return false; } if (strlen($hash) > 22) { $hash = substr($hash,-22); } return base16_encode(base64_decode_ex($hash)); } Given these functions, the base16 representation of your three examples are: 3ac3b4145aa7b9387a46dd7c780c1850 6f80dba665e27749ae88f58eaef5fe84 ec5f74086ec3fab34957d3ef0f838154 Of course, it is important to remember that they were always valid, just formatted differently.
TheKeys at Stack Overflow Visit the source
Other answers
$1$ indeed means that this is a MD5 hash, but crypt generates a random salt. This is why you find a different MD5 value. If you include the generated salt you will find the same result. The salt is base64 encoded in the output, as the hash. The algorithm used is a system wide parameter. Generally this is MD5, you are right.
Edouard A.
I believe the answer to my original question is no, you can't convert from one format to the other. The hashes generated by php crypt() appear to be generate by a version of the FreeBSD MD5 hash implementation created by Poul-Henning Kamp. http://people.freebsd.org/~phk/
TheKeys
From the documentation, this depends on the system. You can force the algorithm used by setting the salt parameter. From the docs: The encryption type is triggered by the salt argument. At install time, PHP determines the capabilities of the crypt function and will accept salts for other encryption types. If no salt is provided, PHP will auto-generate a standard two character salt by default, unless the default encryption type on the system is MD5, in which case a random MD5-compatible salt is generated.
Ray Booysen
From http://php.net/crypt: crypt() will return an encrypted string using the standard Unix DES-based encryption algorithm or alternative algorithms that may be available on the system. You want the http://php.net/md5 function: Calculates the MD5 hash of str using the » RSA Data Security, Inc. MD5 Message-Digest Algorithm, and returns that hash. If the optional raw_output is set to TRUE, then the md5 digest is instead returned in raw binary format with a length of 16. Defaults to FALSE.
Sven Lilienthal
Related Q & A:
- How can I convert UTF-16 file to UTF-8?Best solution by Stack Overflow
- How can I convert Matlab code to c#?Best solution by Stack Overflow
- How can I check if the CC and BCC is valid or not?Best solution by stackoverflow.com
- What can i add in constructors in PHP?Best solution by Stack Overflow
- Is it possible to convert YPbPr output to Coaxial output?Best solution by Yahoo! Answers
Just Added Q & A:
- How many active mobile subscribers are there in China?Best solution by Quora
- How to find the right vacation?Best solution by bookit.com
- How To Make Your Own Primer?Best solution by thekrazycouponlady.com
- How do you get the domain & range?Best solution by ChaCha
- How do you open pop up blockers?Best solution by Yahoo! Answers
For every problem there is a solution! Proved by Solucija.
-
Got an issue and looking for advice?
-
Ask Solucija to search every corner of the Web for help.
-
Get workable solutions and helpful tips in a moment.
Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.