Check if string is an MD5 Hash

52,562

Solution 1

You can check using the following function:

function isValidMd5($md5 ='')
{
    return preg_match('/^[a-f0-9]{32}$/', $md5);
}

echo isValidMd5('5d41402abc4b2a76b9719d911017c592');

The MD5 (Message-digest algorithm) Hash is typically expressed in text format as a 32 digit hexadecimal number.

This function checks that:

  1. It contains only letters and digits (a-f, 0-9).
  2. It's 32 characters long.

Solution 2

Maybe a bit faster one:

function isValidMd5($md5 ='') {
  return strlen($md5) == 32 && ctype_xdigit($md5);
}
Share:
52,562
kmoney12
Author by

kmoney12

Email - [email protected]

Updated on July 09, 2022

Comments

  • kmoney12
    kmoney12 almost 2 years

    I accidentally stopped hashing passwords before they were stored, so now my database has a mix of MD5 Passwords and unhashed passwords.

    I want to loop through and hash the ones that are not MD5. Is it possible to check if a string is an MD5 hash?

  • Gromski
    Gromski over 11 years
    The !empty check is entirely superfluous there.
  • inhan
    inhan over 11 years
    Why do you need to check if it's empty? Won't it already return false if preg_match() does not match?
  • kmoney12
    kmoney12 over 11 years
    What's the accuracy on this? Can I trust it completely? Sorry don't know too much about regular expressions.
  • tsujp
    tsujp over 11 years
    It will return 0 if it doesn't match, synonymous with false. +vote @inhan
  • inhan
    inhan over 11 years
    @hellohellosharp yeah, documentation reads Returns the hash as a 32-character hexadecimal number. which means the value should consist of 0-9 and a-f characters only and it should be 32 characters long.
  • tsujp
    tsujp over 11 years
    @hellohellosharp I only started regular expressions yesterday but this preg_match('/^[a-f0-9]{32}$/' is stating thata string of 32 characters long can only contain letters a-f (hex) and numbers 0-9. There are a few reasons why you can trust this, and cannot. 1. MD5 is 32 characters long, 2. MD5 contains only lowercase alpha characters a through f. Anyone can fake an MD5 hash, there is no surefire method to detect if text, information, is from a certain source unless you go into things like secure login cookies etc..., which is a completely different subject.
  • tsujp
    tsujp over 11 years
    @hellohellosharp Long story short, this method is fine for analyzing the format of the string you are checking.
  • inhan
    inhan over 11 years
    @hellohellosharp something important is, make sure your MD5() call does not include the second parameter that can be converted into true otherwise this function will not help you. Check the raw_output (2nd) parameter in MD5() documentation.
  • Jan Doggen
    Jan Doggen over 10 years
    @hellohellosharp Nobody seems to have answered your 'accuracy' comment yet: this function verifies that a string is in the format of an MD5 hash, it does not validate that it is an actual hashed password - that cannot be determined. It will also return true if one of your unhashed passwords meets the format requirements - but that is unlikely.
  • kyle
    kyle about 10 years
    Thanks! I used it like so: if (!preg_match('/^[a-f0-9]{32}$/', $md5)) {return false;} (not for a password, lol!)
  • laurent
    laurent about 10 years
    +1, probably faster, and also more readable than the regex. It might do an early exit on the strlen call for most invalid strings, then I suspect the ctype_xdigit call is faster than running a regex engine.
  • l00k
    l00k about 10 years
    Note that you can't be 100% sure that string which pass this test is md5 or plain text password. Unlikely, but someone may have a password similar to the md5 format.
  • RaphaelH
    RaphaelH about 10 years
    @non: I do not agree with you. You can be 100% sure that the string is a valid md5 hash. Whether the string was intended to be a valid md5 hash is a whole another point..
  • l00k
    l00k almost 10 years
    @RaphaelH you didnt understand me.. "e4bfb280c702635cf71d46a0c8c33b96" it may be hashed (md5) password or just plain password. You can't be sure :)
  • RaphaelH
    RaphaelH almost 10 years
    @non: Once again, "e4bfb280c702635cf71d46a0c8c33b96" is for 100 percent a valid md5 hash, you can't be sure if it was intended to be one. If it's your password, then it's both valid md5 and your plain password.
  • Jack
    Jack over 9 years
    Why are you using an empty string as default parameter?
  • VeeeneX
    VeeeneX about 9 years
    Yes, you can't be 100% sure, that it is md5 string in order to that, you need to use: !ctype_digit($md5) && ctype_lower($md5) && ctype_alpha($md5)
  • Cliff Burton
    Cliff Burton almost 8 years
    @NullPoiиteя you have a typo: "Its contain only letter and digit (a-z,0-9)" should be "(a-f,0-9)"
  • RaphaelH
    RaphaelH about 7 years
    @VeeeneX Answer might be a little late, but what you suggest is just complete bs and I want to clarify that. I am assuming the representation of the md5 hash as hex string as everyone else here does. It can and mostly does contain digits, so !ctype_digit is wrong. It does not have to be lowercase, so ctype_lower is wrong, nothing wrong with uppercase hashes. It can't have characters beyond f, so ctype_alpha is wrong.
  • xZero
    xZero about 6 years
    Faster only and only if character is shorter than 32. if not, then involves unnecessary function call overhead, in this case strlen
  • xZero
    xZero about 6 years
    Worth noting is that preg_match might not return boolean but int, therefore your function will not work in eg (if(isValidMd5($hash) === true)). Here is faster version, which also overcomes mentioned problem: sandbox.onlinephpfunctions.com/code/…
  • RaphaelH
    RaphaelH about 6 years
    @xZero This is not about 2 function calls versus 1 function call, it's about running a regex engine versus 2 rather lightweight function calls. On my machine the non regex version runs about 75% faster, of course this depends on the input, in my test case random generated, see pastebin.com/BhpPpGyw to try yourself
  • xZero
    xZero about 6 years
    @RaphaelH I completely agree with you. I was not trying to say that your approach is slower, although it sounded like that. I just thought it's worth noting circumstances it is faster with.